如何使它一次只能选择 1 个“能力”类型的对象?

How can make it so only 1 object of type "Ability" can be selected at once?

提问人:HarrisonO 提问时间:8/9/2020 更新时间:8/10/2020 访问量:47

问:

我正在我的游戏中制作一个技能系统,但遇到了一些问题。我设置了一个脚本,告诉我哪个“能力”最接近我的光标,如果是,则更改动画状态。对于我的一个能力,如果选择,调试屏幕会说“最接近的能力是 A”(有效),但如果我的光标靠近另一个,它会说“最接近的能力是 A”,然后是“最接近的能力是 B”。当只应选择一个对象时,这通过触发两个对象上的选择来搞砸我的动画。我的代码在哪里导致此问题发生,我该如何解决它,以便一次只能选择 1 种能力。 提前致谢!

最接近游标脚本

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

public class AtMouseCursor : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        ClosestAbility();
        Vector2 cursorPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        transform.position = cursorPos;
    }
    void ClosestAbility()
    {
        float distanceToClosestAbility = Mathf.Infinity;
        Ability closestAbility = null;
        Ability[] allAbilities = GameObject.FindObjectsOfType<Ability>();

        foreach (Ability currentAbility in allAbilities)
        {
            float distanceToAbility = (currentAbility.transform.position - this.transform.position).sqrMagnitude;
            if (distanceToAbility < distanceToClosestAbility)
            {
                distanceToClosestAbility = distanceToAbility;
                closestAbility = currentAbility;
                UnityEngine.Debug.Log("The Closest Ability is " + closestAbility.name);
            }


        }
        foreach (Ability currentAbility in allAbilities)
        {
            if (currentAbility != closestAbility)
            {
                currentAbility.GetComponent<Ability>().AbilityNotSelected();
            }
            else if (currentAbility == closestAbility)
            {
                currentAbility.GetComponent<Ability>().AbilitySelected();
            }
        }
    }
}

能力脚本(继续能力预制件)

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

public class Ability : MonoBehaviour
{
    
    public Animator anim;
    void Start()
    {
        anim = GetComponent<Animator>();
    }

    public void AbilitySelected()
    {
        
        UnityEngine.Debug.Log("Bruh im selscted");
        anim.SetBool("isSelected", true);
    }

   
    public void AbilityNotSelected()
    {
       
        anim.SetBool("isSelected", false);
    }
}
C# Unity-游戏引擎

评论


答:

1赞 IceGlasses 8/9/2020 #1

您只需要将 Log 语句移到第一个循环之外 [之后]。在你检查了所有这些之前,你不会知道它实际上是最接近的能力。

(也许添加一个不为 null 或不为空的检查。allAbilities


更新 1:在更新所述转换位置之前使用 but 调用。这看起来可能会导致您对最接近旧鼠标位置而不是当前鼠标位置的能力进行动画处理。但是,如果它被调用每一帧,它可能不会引起注意。ClosestAbility()this.transform.positionUpdate()ClosestAbility()

更新2: 我想到的代码:

void ClosestAbility()
{
    float distanceToClosestAbility = Mathf.Infinity;
    Ability closestAbility = null;
    Ability[] allAbilities = GameObject.FindObjectsOfType<Ability>();
    if ((allAbilities == null) || (allAbilities.Length == 0))
    {
        return;
    }

    foreach (Ability currentAbility in allAbilities)
    {
        float distanceToAbility = (currentAbility.transform.position - this.transform.position).sqrMagnitude;
        if (distanceToAbility < distanceToClosestAbility)
        {
            distanceToClosestAbility = distanceToAbility;
            closestAbility = currentAbility;
            UnityEngine.Debug.Log(closestAbility.name + " is close, but there might be an ability that's closer still");
        }
    }
    UnityEngine.Debug.Log("I checked all the abilities and " + closestAbility.name + " is the closest");
    foreach (Ability currentAbility in allAbilities)
    {
        if (currentAbility != closestAbility)
        {
            currentAbility.GetComponent<Ability>().AbilityNotSelected();
        }
        else if (currentAbility == closestAbility)
        {
            currentAbility.GetComponent<Ability>().AbilitySelected();
        }
    }
    UnityEngine.Debug.Log("Finished updating all the animations without any exceptions");
}

更新 3:我对 Unity 完全不熟悉,但既然是 ,我想知道调用充其量是否不必要的,您可以/应该拥有?不过,如果你的动画打开了,它至少在某些时候必须工作,也许。不过,我会检查 GetComponent 调用是否返回您认为它返回的内容。currentAbilityAbilitycurrentAbility.GetComponent<Ability>()currentAbility.AbilityNotSelected()

评论

0赞 HarrisonO 8/9/2020
对不起,我对编码很陌生,我该怎么做?
0赞 HarrisonO 8/9/2020
对不起,这也不起作用。我对为什么会发生这种情况一无所知:|谢谢你不厌其烦地帮助我!
0赞 Ahmet Dara VEFA 8/10/2020 #2

UnityEngine.Debug.Log(“最接近的能力是” + closestAbility.name);

您正在为列表中的每种能力连续调用此值。所以

if (distanceToAbility < distanceToClosestAbility)

在初始 foreach 循环中可以为真两次或更多次。循环本身很好。只需使用

UnityEngine.Debug.Log(“我检查了所有能力,”+ closestAbility.name +“是最接近的”);

此代码来自 IceGlasses 代码,在您第一次 foreach 循环后记录最接近的能力。

第一个主要问题似乎是召唤

最接近能力();

在更新 cursorPos 和 transform.position 之前。这会导致 ClosestAbility 函数使用上一帧的 transform.position 值。

第二个问题似乎是在每一帧调用 ClosestAbility 函数。因此,如果其中一个技能动画花费的时间超过一帧,并且您将光标移近另一个技能,则第二个技能也将被触发。

除非在第二个动画开始播放时停止第一个动画,或者除非调用 ClosestAbility 函数,否则如果没有动画在播放,则可以同时播放 2 个或多个动画。