Unity 两点之间随机曲线动画

最近遇到一个功能就是导弹到目标点要有随机曲线表现,重点要到目标点那里

实现思路

用根据时间流逝用sin函数来处理来回曲线的功能(坐标偏移),加个衰减距离(计算坐标偏移大小)

先上图,最下方有工程下载地址

主要实现代码如下

using UnityEngine;
using Random = UnityEngine.Random;


public enum RandomMoveCoordinates
{
    None,
    XY,
    XZ,
    YZ,
    XYZ
}

public class EffectRandomMove : MonoBehaviour
{
    /// <summary>
    /// 随机偏移半径
    /// </summary>
    public float RandomMoveRadius;

    /// <summary>
    /// 随机偏移移动速度,根据时间累加通过sin算出弧线
    /// </summary>
    public float RandomMoveSpeed;

    /// <summary>
    /// 同上
    /// </summary>
    public float RandomRange;

    /// <summary>
    /// 衰减距离
    /// </summary>
    public float ReduceDistance = 1;

    /// <summary>
    /// 随机模式
    /// </summary>
    public RandomMoveCoordinates RandomMoveCoordinates = RandomMoveCoordinates.None;

    /// <summary>
    /// 控制主要插值到目标点速度
    /// </summary>
    public AnimationCurve Acceleration;
    public float AcceleraionTime = 1;

    /// <summary>
    /// 是否朝向目标
    /// </summary>
    public bool IsLookAt;

    /// <summary>
    /// 移动方向速度,一定要比偏移移动速度要大
    /// </summary>
    public float MoveSpeed;

    /// <summary>
    /// 目标
    /// </summary>
    public Transform tTarget;
    private Vector3 targetPos;

    /// <summary>
    /// 新的随机点和旧的随机点,用于计算差值
    /// </summary>
    private Vector3 smootRandomPos, oldSmootRandomPos;
    private float deltaSpeed;

    /// <summary>
    /// 记录开始时间
    /// </summary>
    private float startTime;

    /// <summary>
    /// 随机数据
    /// </summary>
    private float randomSpeed, randomRadiusX, randomRadiusY;
    private int randomDirection1, randomDirection2, randomDirection3;

    private void Start()
    {
        InitializeDefault();
    }

    private void InitializeDefault()
    {
        smootRandomPos = new Vector3();
        oldSmootRandomPos = new Vector3();
        deltaSpeed = 0;
        startTime = 0;
        randomSpeed = 0;
        randomRadiusX = 0;
        randomRadiusY = 0;
        randomDirection1 = 0;
        randomDirection2 = 0;
        randomDirection3 = 0;

        if (IsLookAt)
            transform.LookAt(tTarget);
        InitRandomVariables();
    }

    private Vector3 GetTarPos()
    {
        if(null != tTarget)
        {
            return tTarget.position;
        }
        return targetPos;
    }

    private void Update()
    {
        Vector3 endPoint = GetTarPos();

        float distance = Vector3.Distance(transform.position, endPoint);

        Vector3 delta = new Vector3();
        if (RandomMoveCoordinates != RandomMoveCoordinates.None)
        {
            //利用sin计算坐标差值
            UpdateSmootRandomhPos();
            delta = smootRandomPos - oldSmootRandomPos;
        }

        float accelerationY = 1;
        if (Acceleration.length > 0)
        {
            float time = (Time.time - startTime) / AcceleraionTime;
            accelerationY = Acceleration.Evaluate(time);
        }
        //不停插值目标位置,关键在于曲线,如果只够大的时候偏移坐标效果很小,感觉就是直接回到目标点
        Vector3 moveDistance = Vector3.MoveTowards(transform.position, endPoint, MoveSpeed * Time.deltaTime * accelerationY);
        //这里加了距离衰减偏移坐标
        Vector3 moveDistanceRandom = moveDistance + delta * Mathf.Min(distance / ReduceDistance, 1);
        transform.LookAt(moveDistanceRandom);
        transform.position = moveDistanceRandom;
        oldSmootRandomPos = smootRandomPos;
    }

    private void InitRandomVariables()
    {
        deltaSpeed = RandomMoveSpeed * Random.Range(1, 1000 * RandomRange + 1) / 1000 - 1;
        startTime = Time.time;
        randomRadiusX = Random.Range(RandomMoveRadius / 20, RandomMoveRadius * 100) / 100;
        randomRadiusY = Random.Range(RandomMoveRadius / 20, RandomMoveRadius * 100) / 100;
        randomSpeed = Random.Range(RandomMoveSpeed / 20, RandomMoveSpeed * 100) / 100;
        randomDirection1 = Random.Range(0, 2) > 0 ? 1 : -1;
        randomDirection2 = Random.Range(0, 2) > 0 ? 1 : -1;
        randomDirection3 = Random.Range(0, 2) > 0 ? 1 : -1;
    }

    private void UpdateSmootRandomhPos()
    {
        float coord1, coord2;
        float time = (Time.time - startTime);

        float timeDegree = time * randomSpeed;
        float delta = time * deltaSpeed;
        coord1 = randomDirection2 * Mathf.Sin(timeDegree) * randomRadiusX;
        coord2 = randomDirection3 * Mathf.Sin(timeDegree + (randomDirection1 * Mathf.PI / 2) * time + Mathf.Sin(delta)) * randomRadiusY;

        if (RandomMoveCoordinates == RandomMoveCoordinates.XY)
            smootRandomPos = new Vector3(coord1, coord2, 0);
        if (RandomMoveCoordinates == RandomMoveCoordinates.XZ)
            smootRandomPos = new Vector3(coord1, 0, coord2);
        if (RandomMoveCoordinates == RandomMoveCoordinates.YZ)
            smootRandomPos = new Vector3(0, coord1, coord2);
        if (RandomMoveCoordinates == RandomMoveCoordinates.XYZ)
            smootRandomPos = new Vector3(coord1, coord2, (coord1 + coord2) / 2 * randomDirection1);
    }
}

  

下面是完整工程下载地址

链接:https://pan.baidu.com/s/13czuQWwAehu5D9vP3Gzpnw 
提取码:js7u 

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值