【问题标题】:Animator.GetFloat returning wrong value unityAnimator.GetFloat 返回错误的值统一
【发布时间】:2020-01-07 03:09:38
【问题描述】:

我有一个包含一堆 AI 僵尸的关卡,目前运行良好,但如果实例化一个相同类型的新预制僵尸,新僵尸将采取相同的行为并在动画师中设置相同的参数,尽管这是问题出在哪里……

这些实例化的 AI 出于某种原因调用 Animator.GetFloat 函数,传递与其他非实例化 AI 相同的东西,但这次它似乎总是返回 0,而对于我来说,我无法弄清楚为什么。

这里的图片显示我目前正在使用这个动画,它使用动画曲线将这个参数设置为1,这正是我想要的。

然后问题出现在代码中。调用似乎返回错误值的地方

更新:有时第一个生成的僵尸将能够获得该值。不知道为什么

这是当前在参数代码中输入的内容,这是对哈希的转换

当播放动画变量并且玩家被碰撞体击中时控制要输出的伤害的我的类。

public class AIDamageTrigger : MonoBehaviour 
{
    // Inspector Variables
    [SerializeField] string         _parameter = "";
    [SerializeField] int            _bloodParticlesBurstAmount  =   10;
    [SerializeField] float          _damageAmount               =   0.1f;
    [SerializeField] bool           _doDamageSound              =   true;
    [SerializeField] bool           _doPainSound                =   true;

    // Private Variables
    AIStateMachine      _stateMachine       = null;
    Animator            _animator           = null;
    int                 _parameterHash      = -1;
    GameSceneManager    _gameSceneManager   = null;
    private bool        _firstContact       = false;        

    // ------------------------------------------------------------
    // Name :   Start
    // Desc :   Called on object start-up to initialize the script.
    // ------------------------------------------------------------
    void Start()
    {
        // Cache state machine and animator references
        _stateMachine = transform.root.GetComponentInChildren<AIStateMachine> ();

        if (_stateMachine != null)
            _animator = _stateMachine.animator;

        // Generate parameter hash for more efficient parameter lookups from the animator
        _parameterHash = Animator.StringToHash (_parameter); 

        _gameSceneManager = GameSceneManager.instance;
    }

    void OnTriggerEnter( Collider col )
    {
        if (!_animator) 
            return;

        //Debug----------------------
        int leftHandHash = Animator.StringToHash("LeftHand");
        int rightHandHash = Animator.StringToHash("RightHand");
        int mouthHash = Animator.StringToHash("Mouth");
        float left = _animator.GetFloat(leftHandHash);
        float right = _animator.GetFloat(rightHandHash);
        float mouth = _animator.GetFloat(mouthHash);
        //Debug.Log(this.gameObject.transform.parent.transform.parent.transform.parent.transform.parent.transform.transform.parent.parent.transform.parent.transform.parent.transform.parent.name + " : " + left);
        //Debug.Log(this.gameObject.transform.parent.transform.parent.transform.parent.transform.parent.transform.transform.parent.parent.transform.parent.transform.parent.transform.parent.name + " : " + right);
        //Debug.Log(this.gameObject.transform.parent.transform.parent.transform.parent.transform.parent.transform.transform.parent.parent.transform.parent.transform.parent.transform.parent.name + " : " + mouth);
        //----------------------------

        if (col.gameObject.CompareTag ("Player") && _animator.GetFloat(_parameterHash) >0.9f)
             _firstContact = true;
    }

    // -------------------------------------------------------------
    // Name :   OnTriggerStay
    // Desc :   Called by Unity each fixed update that THIS trigger
    //          is in contact with another.
    // -------------------------------------------------------------
    void OnTriggerStay( Collider col )
    {
        // If we don't have an animator return
        if (!_animator)
            return;

        int leftHandHash = Animator.StringToHash("LeftHand");
        int rightHandHash = Animator.StringToHash("RightHand");
        int mouthHash = Animator.StringToHash("Mouth");
        float left = _animator.GetFloat(leftHandHash);
        float right = _animator.GetFloat(rightHandHash);
        float mouth = _animator.GetFloat(mouthHash);

        _animator.Update(0);
        // If this is the player object and our parameter is set for damage
        if (col.gameObject.CompareTag ("Player") && _animator.GetFloat(_parameterHash) >0.9f)
        {
            if (GameSceneManager.instance && GameSceneManager.instance.bloodParticles) 
            {
                ParticleSystem system = GameSceneManager.instance.bloodParticles;

                // Temporary Code
                system.transform.position = transform.position;
                system.transform.rotation = Camera.main.transform.rotation;

                var settings = system.main;
                settings.simulationSpace = ParticleSystemSimulationSpace.World;
                system.Emit (_bloodParticlesBurstAmount);
            }

            if (_gameSceneManager!=null)
            {
                PlayerInfo info = _gameSceneManager.GetPlayerInfo( col.GetInstanceID() );
                if (info!=null && info.characterManager!=null)
                {
                    info.characterManager.TakeDamage( _damageAmount, _doDamageSound && _firstContact, _doPainSound );
                }
            }

            _firstContact = false;
        }
    }
}

【问题讨论】:

  • 那么_parameterHash 的值是多少?您可能更想使用例如leftHandHash 而不是?
  • 如果 fps 差异很大,检查动画是否完成 >90% 是一种非常不可靠的方法。我可以建议创建一个事件(在最后一个关键帧上),它会在您的脚本中调用一个函数。
  • 我已经更新了帖子,很抱歉错过了这条信息,我当时很困惑,它让我忘记了
  • 所以我希望它的工作方式是我希望它只在我放置动画曲线的动画中手接触玩家时才造成伤害。由于我没有经历过,您认为实现这一目标的最佳方法是什么?动画曲线只从 0 变为 1,因此检查它是否超过 0.9 只是检查它不是 0 并且在动画中手当前正在接触
  • 公平地说,它似乎在动画师中工作得很好,但由于某种原因我无法获得价值

标签: c# unity3d animator


【解决方案1】:

问题出在你的变量Animator _animator;

你在做_animator = _stateMachine.animator;,而你所有的僵尸都有同一个动画师,为什么你不使用这个:

_animator = gameObject.GetComponent<Animator>();

所以每个僵尸都可以访问它的动画师。

【讨论】:

  • 我最终退回了一个版本,因为我当时无法弄清楚问题所在。无论如何感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 2019-02-03
  • 1970-01-01
相关资源
最近更新 更多