首页 > 解决方案 > Playing a random animation every time an object passed

问题描述

I am currently in the process of making a game and I am trying to have a mirror play a random animation as the player walks past it. I managed to get it working, sort-of, and am having some troubles with it.

So first I created an idle animation along with three random animations to be activated as the player walks by and from the idle animation. I then created a simple transition to each of the three states leaving the standard exit time and transition duration on. I than created this script to try to activate the animations:

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

public class mirrorActivate : MonoBehaviour
{
    private GameObject FSSecurity;
    public GameObject mirrorblank;
    public List<AnimationClip> anim = new List<AnimationClip>();
    // Start is called before the first frame update
    private void Awake()
    {

    }
    void Start()
    {
        FSSecurity = GameObject.Find("Female Security");
    }

    // Update is called once per frame
    void Update()
    {
        if (FSSecurity.transform.position.x == 10)
        {
            StartAnimation();
        }
    }
    public void StartAnimation()
    {
        int random = Random.Range(0, anim.Count);
        mirrorblank.GetComponent<Animator>().Play(anim[random].name);
    }
}

What's working: It is seemingly playing a random animation every time the player walks to this location.

What's not working?: 1. Upon entering scene idle animation immediately triggers one of the three animations without the if statement being activated. ((It should be in idle and only switch to one of the three randomly if if() is true)) 2. Due to floating point precision using == is not practical, this theoretically could be solved if I use a range with <= and >= rather than ==. But if there is a better solution to activate the player passing an object I am open to suggestions. 3. Animations when played randomly are not fully playing the full time the animation should last. 4. Final issue after activated they are not returning to idle state until next activation.

What I am looking for: Random animation to play each time user walks passed object and as it finishes return to idle. And as a side note is there a more effective way to know when player passes object (I am using 2D)

(for some reason not letting me put unity2d tag on the post)

enter image description here

Simple transitions between, no triggers set or anything

enter image description here

标签: unity3danimation

解决方案


最后!经过一些漫长而曲折的转弯后,我终于想出了一个我认为效果很好的合理解决方案。

问题1解决方案:
为了防止在if()语句被触发之前触发任何动画,移除从空闲到随机状态的转换。

问题 2 解决方案:
简单地使用范围来解决使用 == 比较浮点精度的问题。请评论任何其他更好的方法来解决这个问题。

问题 3 解决方案:
由于不断触发,动画没有完全按照所需的动画时间运行。如果玩家 >= 10 是导致它激活的唯一参数,因此要使用布尔值的简单解决方案来解决。如果 player.transform >= 10 并且布尔值为 true 开始动画。如果玩家在范围之外,则布尔值为假。在 StartAnimation() 中设置布尔值太真实。

问题 4 解决方案:
现在移除了从空闲到随机动画的转换,而是创建从随机状态到退出的转换。不需要在空闲动画和随机动画之间进行交互的过渡。

完整代码以获得更好的细节:

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

public class mirrorActivate : MonoBehaviour
{
    private GameObject FSSecurity;
    public GameObject mirrorblank;
    public List<AnimationClip> anim = new List<AnimationClip>();
    bool isPlayingAlready = false;
    // Start is called before the first frame update
    private void Awake()
    {

    }
    void Start()
    {
        FSSecurity = GameObject.Find("Female Security");
    }

    // Update is called once per frame
    void Update()
    {
        if (FSSecurity.transform.position.x >= 10 && isPlayingAlready == false)
        {
            StartAnimation();
        }
        if (FSSecurity.transform.position.x <= 10 && isPlayingAlready == true)
        {
            isPlayingAlready = false;
        }
    }
    public void StartAnimation()
    {
        int random = Random.Range(0, anim.Count);
        mirrorblank.GetComponent<Animator>().Play(anim[random].name);
        isPlayingAlready = true;
    }
}

动画控制器视图:

在此处输入图像描述

动画过渡视图(这可能会根据您的需要而改变,但出于此目的..):

在此处输入图像描述

我希望这可以帮助任何可能遇到同样问题的人,这可以通过任何你用来激活随机动画的东西来完成,无论是碰撞还是其他东西。


推荐阅读