C# 如何在每个条件下仅使用一次标志?

C# 如何在每个条件下仅使用一次标志?,c#,unity3d,C#,Unity3d,此简单类附加到游戏中的某些对象: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class InteractableItem : MonoBehaviour { public enum InteractableMode { Description, Action,

此简单类附加到游戏中的某些对象:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class InteractableItem : MonoBehaviour
{
    public enum InteractableMode
    {
        Description,
        Action,
        ActionWithoutThrow
    };

    public InteractableMode interactableMode = InteractableMode.Description;
    public float distance;

    [TextArea(1, 10)]
    public string description = "";

    public bool IsAnyAction()
    {
        return interactableMode == InteractableMode.ActionWithoutThrow || interactableMode == InteractableMode.Action;
    }
}
例如,脚本附加到游戏对象: 因此,当播放器与安全键盘的距离接近1.7时,它将触发以下事件:

在此脚本中,我使用InteractiableItem枚举:

using UnityEngine;
using System;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;

[RequireComponent(typeof(Animator))]
public class IKControl : MonoBehaviour
{
    public InteractableItem[] lookObj = null;
    public GameObject objToThrow;
    public Text text;
    public float weightDamping = 1.5f;
    public bool RightHandToTarget = true;
    public float throwSpeed;
    public bool handFinishedMove = false;

    private List<InteractableItem> allDetectedItems;
    private Animator animator;
    private InteractableItem lastPrimaryTarget;
    private float lerpEndDistance = 0.1f;
    private float finalLookWeight = 0;
    private bool transitionToNextTarget = false;

    void Start()
    {
        animator = GetComponent<Animator>();
        allDetectedItems = new List<InteractableItem>();
    }

    // Callback for calculating IK
    void OnAnimatorIK()
    {
        if (lookObj != null)
        {
            InteractableItem primaryTarget = null;
            float closestLookWeight = 0;

            // Here we find the target which is closest (by angle) to the players view line
            allDetectedItems.Clear();
            foreach (InteractableItem target in lookObj)
            {
                Vector3 lookAt = target.transform.position - transform.position;
                lookAt.y = 0f;

                // Filter out all objects that are too far away
                if (lookAt.magnitude > target.distance) continue;

                float dotProduct = Vector3.Dot(new Vector3(transform.forward.x, 0f, transform.forward.z).normalized, lookAt.normalized);
                float lookWeight = Mathf.Clamp(dotProduct, 0f, 1f);
                if (lookWeight > 0.1f && lookWeight > closestLookWeight)
                {
                    closestLookWeight = lookWeight;
                    primaryTarget = target;
                    allDetectedItems.Add(target);
                }
            }

            if (primaryTarget != null)
            {
                if ((lastPrimaryTarget != null) && (lastPrimaryTarget != primaryTarget) && (finalLookWeight > 0f))
                {
                    // Here we start a new transition because the player looks already to a target but
                    // we have found another target the player should look at
                    transitionToNextTarget = true;
                }
            }

            // The player is in a neutral look position but has found a new target
            if ((primaryTarget != null) && !transitionToNextTarget)
            {
                if(primaryTarget.interactableMode == InteractableItem.InteractableMode.ActionWithoutThrow)
                {
                    RightHandToTarget = true;
                }

                lastPrimaryTarget = primaryTarget;
                //finalLookWeight = Mathf.Lerp(finalLookWeight, closestLookWeight, Time.deltaTime * weightDamping);
                finalLookWeight = Mathf.Lerp(finalLookWeight, 1f, Time.deltaTime * weightDamping);
                float bodyWeight = finalLookWeight * .75f;
                animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
                animator.SetLookAtPosition(primaryTarget.transform.position);

                if (RightHandToTarget && primaryTarget.IsAnyAction())
                {
                    Vector3 relativePos = primaryTarget.transform.position - transform.position;
                    Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
                    animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 1f * closestLookWeight);
                    animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);

                    // -> new code block
                    if (finalLookWeight > 0.95f) // here you can play with a value between 0.95f -> 1.0f
                    {
                        

                        if(primaryTarget.interactableMode == InteractableItem.InteractableMode.Action)
                        // call your funtion to shoot something here
                        StartCoroutine(ThrowObject(objToThrow.transform, primaryTarget.transform.position, 30f));
                    }

                    if(finalLookWeight > 0.9f)
                    {
                        handFinishedMove = true;
                    }
                }
            }

            // Let the player smoothly look away from the last target to the neutral look position
            if ((primaryTarget == null && lastPrimaryTarget != null) || transitionToNextTarget)
            {
                finalLookWeight = Mathf.Lerp(finalLookWeight, 0f, Time.deltaTime * weightDamping);
                float bodyWeight = finalLookWeight * .75f;
                animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
                animator.SetLookAtPosition(lastPrimaryTarget.transform.position);

                if (RightHandToTarget)
                {
                    Vector3 relativePos = lastPrimaryTarget.transform.position - transform.position;
                    Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
                    animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
                    animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
                    animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.5f * closestLookWeight);
                    animator.SetIKPosition(AvatarIKGoal.RightHand, lastPrimaryTarget.transform.position);
                }

                if (finalLookWeight < lerpEndDistance)
                {
                    transitionToNextTarget = false;
                    finalLookWeight = 0f;
                    lastPrimaryTarget = null;
                }
            }

            // Show primary object found by the player
            if (primaryTarget != null)
            {
                text.text = primaryTarget.description;
            }
            else
            {
                text.text = "";
            }
        }
    }

    IEnumerator ThrowObject(Transform objectToMove, Vector3 toPosition, float duration)
    {
        float counter = 0;

        while (counter < duration)
        {
            counter += Time.deltaTime;
            Vector3 currentPos = objectToMove.position;

            float time = Vector3.Distance(currentPos, toPosition) / (duration - counter) * Time.deltaTime;

            objectToMove.position = Vector3.MoveTowards(currentPos, toPosition, time);

            yield return null;
        }
    }
}
问题是在最后一个脚本解锁中,问题是playAnimOnce标志始终在false和true之间变化。我需要以某种方式使用标志,但也要检查与安全键盘的距离。我可以在解锁箱中添加一个本地距离检查,检查与播放器的距离,或者检查播放器与安全键盘之间的距离

但其思想是在许多对象上使用InteractiableItem脚本来执行操作或获取描述。 但我想用InteractiableItem中的距离来做。如果播放器与安全键盘的距离为1.7,则在解锁箱脚本中执行某些操作

如果玩家与其他对象(例如树)的距离为55,则对树进行处理


问题有点长,但所有脚本都是连接在一起的。我不确定要从脚本中减少什么。

我建议不要检查每一帧上的标志,而是使用事件。当交互完成时,尝试在
interactiableitem
上放置一个事件,然后在
UnlockCrate
中创建一个方法,该方法可以注册到属于键盘的
interactiableitem
上的事件,并将代码放在其中,使板条箱执行它需要执行的任何操作(你的问题并不能真正解释这一点,所以我不能说得更具体)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;

public class UnlockCrate : MonoBehaviour
{
    public Animation anim;
    public IKControl ikControl;
    public GameObject securityKeyPad;
    public CinemachineVirtualCamera virtualCam;
    public CinemachineFreeLook freeLookCam;
    public CamerasControl camerasContorl;

    private bool playAnimOnce = false;

    private void Update()
    {
        if (!playAnimOnce)
        {
            if (ikControl.handFinishedMove == true)
            {
                securityKeyPad.SetActive(true);
                virtualCam.enabled = true;
                freeLookCam.enabled = false;
                Cursor.visible = true;
                camerasContorl.enabled = false; 
            }

            playAnimOnce = true;
        }
        else if (playAnimOnce)
        {
            securityKeyPad.SetActive(false);
            virtualCam.enabled = false;
            freeLookCam.enabled = true;
            Cursor.visible = false;
            camerasContorl.enabled = true;
            playAnimOnce = false;
        }
    }
}