unity3d - 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)
Simple transitions between, no triggers set or anything
解决方案
最后!经过一些漫长而曲折的转弯后,我终于想出了一个我认为效果很好的合理解决方案。
问题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;
}
}
动画控制器视图:
动画过渡视图(这可能会根据您的需要而改变,但出于此目的..):
我希望这可以帮助任何可能遇到同样问题的人,这可以通过任何你用来激活随机动画的东西来完成,无论是碰撞还是其他东西。
推荐阅读
- node.js - Jsonwebtoken 验证导致 NGINX 超时
- python-3.x - python concurrent.futures 跳过超时进程
- r - 如何将变量的名称及其结果插入 R 中的绘图中
- node.js - AWS S3 访问被本地主机拒绝,但在部署时工作
- php - 如何从xml中获取数据?
- c++ - 为什么可以通过构造函数将临时值分配给引用?
- html - 让网页占据 60% 并居中?
- android - 将值设置为进度后如何保存 SeekBar 拇指位置?
- python - 如何计算数据框中一行中非 NaN 列的数量?
- javascript - 对漂亮的 DND 做出反应 - 我得到“无法找到 id:1 的可拖动对象”