Unity3d 制作物品平滑运动

直接贴代码了

using UnityEngine; 
using System;
using System.Collections;
using System;
using DataTable;

public class ObjDropItem : ObjBase {
	//类型
	public override OBJ.TYPE GetObjType() { return OBJ.TYPE.DROPITEM; }

	public const float MAXSPEED = 20;
	enum State
	{
		Load,
		Delay,
		Droping,
		StayOnGround,
		Pickup,
		FlyToPlayer,
		Destory,
	}

	//外置表现参数
	[Tooltip("飞到玩家身上那个高度位置")]
	public float PlayerOffset = 1.4f;

	[Tooltip("开启安全模式(TotalLifeTime秒后强制删除)")]
	public bool SafeMode = true;

	[Tooltip("存在最长时间(秒)")]
	public float TotalLifeTime = 300;

	[Tooltip("掉落都地上高度")]
	public float DropHight = 0.5f;

	[Tooltip("掉落都地上用时")]
	public float DropTime = 0.3f;

	[Tooltip("多长时间后出现")]
	public float DelayTime = 0.5f;

	[Tooltip("自动拾取距离")]
	public float AutoPickUpDistance = 2.0f;

	[Tooltip("在地上呆的时间")]
	public float DropOverDelayTime = 0.2f;

	[Tooltip("物品速度")]
	[Range(0, 15)]
	public float MoveSpeed = 10.0f;

	[Tooltip("距离多少是已经飞到玩家身上")]
	public float MaxDistance = 0.2f;

	[Tooltip("控制点离我的直线距离")]
	public float ControlPointOffsetDistance = 3.0f;

	[Tooltip("控制点高度")]
	public float ControlPointOffsetHeight = 2.0f;

	[Tooltip("控制点速度,必须要大于物品速度")]
	[Range(15, 25)]
	public float ControlPointSpeed = 15.0f;

	[Tooltip("速度增量")][Range(0,2)]
	public float AccSpeed = 0.1f;


	DropItemController mController;

	//状态
	private State mState = State.Load;

	//生命时间
	private DateTime mLifeTime = DateTime.Now;

	//是否可以自动拾取
	private bool mCanAutoPickup = false;

	//拥有者id
	private bool mOwnerIsMe;

	//拥有者拾取保护时间
	private DateTime mOwnerPickUpProtectionTime;

	//飞往目标点(也就是服务端实际坐标)
	private Vector3 mTargetPos;

	//控制点
	private Vector3 mControlPoint;
	//控制点
	private bool mControlPointReached;
	//控制点速度
	private float mControlPointMoveSpeed;

	//移动速度
	private float mMoveSpeed;

	public virtual void Awake()
	{
#if !UNITY_EDITOR
try
{
#endif

		base.Awake();
		
#if !UNITY_EDITOR
}
catch (Exception ex)
{
    Logger.Error(ex.ToString());
}
#endif
	}

	//重置
	public override void Reset()
	{
		base.Reset();
		mState = State.Load;
		mLifeTime = DateTime.Now.AddSeconds(TotalLifeTime);
		mCanAutoPickup = false;
		mOwnerPickUpProtectionTime = DateTime.Now;
		
	}

	//初始化
	public override bool Init(InitBaseData initData, Action callback = null)
	{
		base.Init(initData);

		Reset();

		InitDropItemData data = initData as InitDropItemData;

		mOwnerIsMe = false;
		mCanAutoPickup = false;
		var player = ObjManager.Instance.MyPlayer;
		if (player)
		{
			if (player.GetObjId() == data.Owner)
			{
				mOwnerIsMe = true;
				mCanAutoPickup = true;
			}
		}
		mOwnerPickUpProtectionTime = DateTime.Now.AddSeconds(data.RemianSeconds);
		mLifeTime = DateTime.Now.AddSeconds(TotalLifeTime);

		float height = GameLogic.Instance.Scene.GetTerrainHeight(data.TargetPos) + 0.1f;
		mTargetPos = new Vector3(data.TargetPos.x, height, data.TargetPos.y);

		LoadRes(() =>
		{
			if (true != data.PlayDrop)
			{//需要播放掉落动画
				Position = mTargetPos;
				mState = State.StayOnGround;
			}
			else
			{//不需要播放掉落动画
				this.StartCoroutine(Delay());
				mState = State.Delay;
			}

			if (null != callback)
				callback();

			mController = mModel.GetComponent<DropItemController>();
			if (null != mController)
			{
				mController.ShowModel(true);
				mController.ShowEffect(false);
			}
		});

		return true;
	}

	//是否可以被拾取
	public bool CanPickup()
	{
		if (State.StayOnGround != mState &&
			State.Pickup != mState)
		{//只有停留在地上这种状态才能被拾取
			return false;
		}
			
		if (DateTime.Now<mOwnerPickUpProtectionTime)
		{//当前时间在拥有者保护时间内
			return mOwnerIsMe;
		}
		else 
		{//过了拥有者保护时间谁都可以拾取
			return true;
		}
	}

	void Update () {
#if !UNITY_EDITOR
try
{
#endif
		if (true==SafeMode)
		{
			if (DateTime.Now > mLifeTime)
			{//为了安全,怎么也该消失了
				Logger.Warn("Drop item[{0}] stays too long", mObjId);
				mState = State.Destory;
				if (ObjManager.Instance.FindObjById(mObjId).Equals(this))
				{
					ObjManager.Instance.RemoveObj(mObjId);
				}
				else
				{
					base.Destroy();
				}
				return;
			}
		}
		

		var player = ObjManager.Instance.MyPlayer;
		if (null == player)
			return;

		if (State.StayOnGround == mState)
		{//停在地上
			if (CanPickup() && mCanAutoPickup)
			{//可以自动拾取
				float distance = Vector2.Distance(player.Position.xz(), Position.xz());
				if (distance <= AutoPickUpDistance)
				{//距离足够近
					var control = UIManager.Instance.GetController(UIConfig.SettingUI);
					if ((bool)control.CallFromOtherClass("CanPiackUpItem", new object[] { mDataId }))
					{//是否可拾取这种类型物品
						Pickup();
					}
					mCanAutoPickup = false;
				}
			}
		}
		else if (State.FlyToPlayer == mState)
		{//我拾取成功,物品正在往我身上飞
			var delta = Time.deltaTime;

			var temp = player.Position;
			temp.y += PlayerOffset;
			//控制点朝着主角飞
			if(!mControlPointReached)
			{
				float distance = Vector2.Distance(temp, mControlPoint);
				if (distance <= MaxDistance)
				{//当前已经飞到了
					mControlPointReached = true;
				}
				else
				{
					mControlPointMoveSpeed += delta * AccSpeed;
					mControlPointMoveSpeed = Math.Min(mControlPointMoveSpeed, MAXSPEED);
					float moveDis = mControlPointMoveSpeed * delta;
					if (moveDis >= distance)
					{//这一步就飞到了
						mControlPointReached = true;
					}
					else
					{//继续移动
						var controlPointDir = (temp - mControlPoint).normalized;
						mControlPoint += controlPointDir * moveDis;
					}
				}
			}

			if (mControlPointReached)
			{
				mControlPoint = temp;
			}
			
			

			{//自己朝着控制点飞
				float dis = Vector3.Distance(mControlPoint, Position);

				if (dis <= MaxDistance && mControlPointReached)
				{
					mState = State.Destory;
					Destroy();
					return;
				}
				else
				{
					mMoveSpeed += AccSpeed * delta;
					mMoveSpeed = Math.Min(mMoveSpeed, MAXSPEED);
					float moveDis = mMoveSpeed * delta;
					if(moveDis>=dis)
					{
						Position = mControlPoint;
						if (mControlPointReached)
						{
							mState = State.Destory;
							Destroy();
							return;
						}
					}
					else
					{
						var dir = (mControlPoint - Position).normalized;
						Position = Position + dir * moveDis;
					}
				}
			}		
		}
	

#if !UNITY_EDITOR
}
catch (Exception ex)
{
    Logger.Error(ex.ToString());
}
#endif
}

	//拾取
	public void Pickup()
	{
		if(CanPickup())
		{
			NetManager.Instance.SendPickUpItemRequest(GetObjId());
			mState = State.Pickup;
		}
		mCanAutoPickup = false;
	}

	protected virtual void LoadRes(Action callback = null)
	{
		string prafabPath = "";

		var table = Table.GetItemBase(mDataId);
		if(null==table)
		{
			Logger.Error("NULL==Table.GetItemBase({0})", mDataId);
		}
		else
		{
			var tableDrop = Table.GetDropModel(table.DropModel);
			if (null == tableDrop)
			{
				Logger.Error("NULL==Table.GetDropModel({0})", table.DropModel);
			}
			else
			{
				prafabPath = tableDrop.ModelPath;
			}
		}

		if ("" == prafabPath)
		{
			Logger.Error("null==prafabPath)");
			return;
		}

        UniqueResourceId = GetNextUniqueResourceId();
        var resId = UniqueResourceId;
        ComplexObjectPool.NewObject(prafabPath, model =>
        {
            if (resId != UniqueResourceId)
            {
                return;
            }
            SetModel(model);
            //SetScale((float)tableDrop.aScale); 这个缩放放到prefab上

            if (null != callback)
            {
                callback();
            }            
        });
	}

	void PlayDropSound()
	{
		var table = Table.GetItemBase(mDataId);
		if (null != table)
		{
			var tableDrop = Table.GetDropModel(table.DropModel);
			if (null != tableDrop)
			{
				SoundManager.Instance.PlaySoundEffect(tableDrop.SoundId);
			}
		}
	}
	IEnumerator Delay()
	{
		mState = State.Delay;

		var renderers = mModel.GetComponentsInChildren<Renderer>();
		foreach (var renderer in renderers)
		{
			renderer.enabled = false;
		}

		yield return new WaitForSeconds(DelayTime);

		foreach (var renderer in renderers)
		{
			renderer.enabled = true;
		}


		DropToTargetPos();
	}

	void DropToTargetPos()
	{
		mState = State.Droping;

		Vector3[] paths=new Vector3[3];
		paths[0] = Position;
		paths[1] = (mTargetPos+Position)/2;
		paths[1].y = Position.y + DropHight;
		paths[2] = mTargetPos;

		iTween.MoveTo(gameObject, iTween.Hash("path", paths, "movetopath", true, "orienttopath", false, "time", DropTime, "easetype", iTween.EaseType.linear, "oncomplete", "DropOver"));

	}

	void DropOver()
	{
		this.StartCoroutine(DropOverStay());
	}

	IEnumerator DropOverStay()
	{
		yield return new WaitForSeconds(DropOverDelayTime);
		mState = State.StayOnGround;
		PlayDropSound();
	}


	public override void Destroy()
	{
		if(State.FlyToPlayer==mState)
		{
			return;
		}

		base.Destroy();
	}

	public void FlyToPlayer()
	{
		if (null != mController)
		{
			mController.ShowModel(false);
			mController.ShowEffect(true);
		}
		var myPos = ObjManager.Instance.MyPlayer.Position;
		var dir = (Position-myPos).normalized;

		mControlPoint = Position + dir * ControlPointOffsetDistance;
		mControlPoint.y += ControlPointOffsetHeight;
		mControlPointMoveSpeed = ControlPointSpeed;
		mMoveSpeed = MoveSpeed;
		mControlPointReached = false;

		mState=State.FlyToPlayer;
	}

}

  

原文地址:https://www.cnblogs.com/mrblue/p/4916695.html