在 Unity 脚本上检查 Animator 仅适用于第一个对象
Checking Animator on Unity script only work on first Object
我先解释一下问题:)
我有英雄也有敌人。这是一款格斗游戏。英雄和敌人在动画控制器中都有 idle、block、punch 和 getHit 动画和状态。英雄和敌人都附有脚本。英雄由玩家控制,然后敌人由 AI 控制。
现在我先将脚本附加到英雄,然后再附加到敌人。现在,当敌人出拳时,如果英雄没有防守,英雄就会受到打击。但是如果敌人没有阻挡并且英雄击中敌人则不会受到击中。 这是因为脚本先附在英雄身上。
现在,如果我从两者中删除脚本并首先将敌人脚本附加到敌人,然后将英雄脚本附加到英雄。智慧反之亦然。在敌人身上会记录命中,在英雄身上不会记录命中。
我不确定为什么会这样,我尝试了不同的方法,但问题仍然存在。
我也尝试在网上到处寻找解决方案,但 none 解决了我的问题。
谢谢:)
下面是检查敌人是否能承受攻击的敌人脚本
void Update () {
myTick++;
currentTick = myTick;
GameObject player = GameObject.Find("theDude");
Animator pAnim = player.GetComponent<Animator>();
//Getting Hit
if (pAnim.GetBool("tIsPunching"))
{
if (anim.GetBool("bEnemyIsDefending") == false)
{
Debug.Log("enemy got hit");
anim.SetTrigger("tEnemyGotHit");
anim.SetBool("bEnemyIsDefending", true);
}
}
}
这是检查英雄是否可以命中的英雄脚本。
void Update () {
totalTime += Time.deltaTime;
GameObject enemy = GameObject.Find("Enemy");
Animator eAnim = enemy.GetComponent<Animator>();
//Getting Hit
if (eAnim.GetBool("tEnemyIsPunching"))
{
if (anim.GetBool("bIsDefending") == false)
{
Debug.Log("player got hit");
anim.SetTrigger("tGotHit");
}
}
}
我以前有一个 public 游戏对象,而不是获取对象,并将英雄和敌人附加到各自的 类 中。但这没有任何区别。
我认为你的问题在于你使用触发器 tEnemyIsPunching
和 tIsPunching
。只要触发发生转换,触发器就会重置
(参见:https://docs.unity3d.com/Manual/AnimationParameters.html)。
在您的情况下,tIsEnemyPunching
或 (tIsPunching
) 在设置时在同一帧中重置。这是一个示例,说明如果先添加英雄脚本,您的游戏中的更新循环可能会是什么样子:
Hero Update()
Check if enemy is punching
He is not, so don't do anything
Enemy Update()
Punch! Set 'bIsEnemyPunching' = true
Animation Update()
bIsEnemyPunching is true so transition to the punching animation
reset bIsEnemyPunching = false
在下一次更新中让我们看看英雄更新中发生了什么:
Hero Update()
Check bIsEnemyPunching
bIsEnemyPunching was reset in the previous frame, so it is false
Since the enemy isn't punching don't do anything
所以 Hero 永远看不到拳头,因为 bIsEnemyPunching
在 Hero 进行更改以检查它之前就被重置了。
这就是添加脚本的顺序很重要的原因。无论哪个脚本首先更新都能够打孔,因为第二个脚本将在重置之前看到触发器。但是,要更新的第二个脚本将永远无法打孔,因为在其他脚本有机会更新之前触发器已重置。
一种解决方案是检查动画状态的名称而不是触发值。
static int punchStateHash = Animator.StringToHash("Punch");
AnimatorStateInfo enemyState = eAnim.GetCurrentAnimatorStateInfo(0);
if (enemyState.nameHash == punchStateHash){
//The enemy is punching!
}
或者,每当一拳被触发时,只需调用一个函数来处理正在被击打的角色。所以当敌人打英雄时,敌人的 Punch(...)
函数应该调用英雄的 TakePunch(...)
(或者任何你想调用的函数)。英雄然后检查自己的状态以确定他是否正在阻塞。
补充说明
您应该避免在更新函数中使用以下代码:
GameObject player = GameObject.Find("theDude");
Animator pAnim = player.GetComponent<Animator>();
这些函数非常慢,因为 Unity 必须在所有对象中搜索名为 theDude
的对象,然后搜索它的所有组件以找到动画师。这样做一次并保存结果。
我先解释一下问题:)
我有英雄也有敌人。这是一款格斗游戏。英雄和敌人在动画控制器中都有 idle、block、punch 和 getHit 动画和状态。英雄和敌人都附有脚本。英雄由玩家控制,然后敌人由 AI 控制。
现在我先将脚本附加到英雄,然后再附加到敌人。现在,当敌人出拳时,如果英雄没有防守,英雄就会受到打击。但是如果敌人没有阻挡并且英雄击中敌人则不会受到击中。 这是因为脚本先附在英雄身上。
现在,如果我从两者中删除脚本并首先将敌人脚本附加到敌人,然后将英雄脚本附加到英雄。智慧反之亦然。在敌人身上会记录命中,在英雄身上不会记录命中。
我不确定为什么会这样,我尝试了不同的方法,但问题仍然存在。
我也尝试在网上到处寻找解决方案,但 none 解决了我的问题。
谢谢:)
下面是检查敌人是否能承受攻击的敌人脚本
void Update () {
myTick++;
currentTick = myTick;
GameObject player = GameObject.Find("theDude");
Animator pAnim = player.GetComponent<Animator>();
//Getting Hit
if (pAnim.GetBool("tIsPunching"))
{
if (anim.GetBool("bEnemyIsDefending") == false)
{
Debug.Log("enemy got hit");
anim.SetTrigger("tEnemyGotHit");
anim.SetBool("bEnemyIsDefending", true);
}
}
}
这是检查英雄是否可以命中的英雄脚本。
void Update () {
totalTime += Time.deltaTime;
GameObject enemy = GameObject.Find("Enemy");
Animator eAnim = enemy.GetComponent<Animator>();
//Getting Hit
if (eAnim.GetBool("tEnemyIsPunching"))
{
if (anim.GetBool("bIsDefending") == false)
{
Debug.Log("player got hit");
anim.SetTrigger("tGotHit");
}
}
}
我以前有一个 public 游戏对象,而不是获取对象,并将英雄和敌人附加到各自的 类 中。但这没有任何区别。
我认为你的问题在于你使用触发器 tEnemyIsPunching
和 tIsPunching
。只要触发发生转换,触发器就会重置
(参见:https://docs.unity3d.com/Manual/AnimationParameters.html)。
在您的情况下,tIsEnemyPunching
或 (tIsPunching
) 在设置时在同一帧中重置。这是一个示例,说明如果先添加英雄脚本,您的游戏中的更新循环可能会是什么样子:
Hero Update()
Check if enemy is punching
He is not, so don't do anything
Enemy Update()
Punch! Set 'bIsEnemyPunching' = true
Animation Update()
bIsEnemyPunching is true so transition to the punching animation
reset bIsEnemyPunching = false
在下一次更新中让我们看看英雄更新中发生了什么:
Hero Update()
Check bIsEnemyPunching
bIsEnemyPunching was reset in the previous frame, so it is false
Since the enemy isn't punching don't do anything
所以 Hero 永远看不到拳头,因为 bIsEnemyPunching
在 Hero 进行更改以检查它之前就被重置了。
这就是添加脚本的顺序很重要的原因。无论哪个脚本首先更新都能够打孔,因为第二个脚本将在重置之前看到触发器。但是,要更新的第二个脚本将永远无法打孔,因为在其他脚本有机会更新之前触发器已重置。
一种解决方案是检查动画状态的名称而不是触发值。
static int punchStateHash = Animator.StringToHash("Punch");
AnimatorStateInfo enemyState = eAnim.GetCurrentAnimatorStateInfo(0);
if (enemyState.nameHash == punchStateHash){
//The enemy is punching!
}
或者,每当一拳被触发时,只需调用一个函数来处理正在被击打的角色。所以当敌人打英雄时,敌人的 Punch(...)
函数应该调用英雄的 TakePunch(...)
(或者任何你想调用的函数)。英雄然后检查自己的状态以确定他是否正在阻塞。
补充说明
您应该避免在更新函数中使用以下代码:
GameObject player = GameObject.Find("theDude");
Animator pAnim = player.GetComponent<Animator>();
这些函数非常慢,因为 Unity 必须在所有对象中搜索名为 theDude
的对象,然后搜索它的所有组件以找到动画师。这样做一次并保存结果。