日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

各种Camera,总有一款适合你(二)

發(fā)布時(shí)間:2025/3/15 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 各种Camera,总有一款适合你(二) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  在實(shí)際的項(xiàng)目開發(fā)中,一般需要程序抽象出一些在幾何意義上有明確意義的參數(shù),這樣方便策劃或美術(shù)在自己的機(jī)器上進(jìn)行調(diào)試。

  下面是一個(gè)可變參的地下城攝像機(jī)的簡單實(shí)現(xiàn):

// 第三人稱攝像機(jī),平移和旋轉(zhuǎn)會(huì)同時(shí)進(jìn)行平滑 public class ThirdPersonalCamera : MonoBehaviour {/// Camera Control Paramspublic GameObject Target = null;public float Distance = 10f;public float RotateX = 0f; // pitch 俯仰public float RotateY = 0f; // yaw 偏航public float SmoothTime = 0.01f; // 平滑時(shí)間,默認(rèn)為1spublic float ScrollWheelSpeed = 1000f; // 中軸調(diào)整速度public Vector3 TargetOffset = Vector3.zero; // 目標(biāo)偏移量private Vector3 Velocity = Vector3.zero; // 平滑初速度private Vector3 Offset = Vector3.zero; // 根據(jù)上面三個(gè)變量計(jì)算出private const float MinDistance = 5f; // 鏡頭最近距離private const float MaxDistance = 100f; // 鏡頭最遠(yuǎn)距離void Start(){if (Target == null) return;}public void Shake(){StartCoroutine("ShakeCoroutine");}void LateUpdate(){if (Target == null) return;UpdateDistance();float radX = Mathf.Deg2Rad * RotateX;float radY = Mathf.Deg2Rad * RotateY;Offset.x = Distance * Mathf.Cos(radX) * Mathf.Cos(radY);Offset.z = Distance * Mathf.Cos(radX) * Mathf.Sin(radY);Offset.y = Distance * Mathf.Sin(radX);Vector3 targetPos = Target.transform.position + Offset + TargetOffset;transform.position = Vector3.SmoothDamp(transform.position, targetPos, ref Velocity, SmoothTime);transform.LookAt(Target.transform.position + TargetOffset);}private void UpdateDistance(){float horizontal = Input.GetAxis("Mouse ScrollWheel") * ScrollWheelSpeed * Time.deltaTime;Distance -= horizontal;}}

  可以看到抽象出的控制參數(shù)主要包括:攝像機(jī)分別繞X軸和Y軸的旋轉(zhuǎn)、攝像機(jī)距離角色的距離、以及用來控制平滑時(shí)間的參數(shù)。

  注意,上面這段代碼的實(shí)現(xiàn)中,position和rotation是同時(shí)進(jìn)行平滑的,下面來看另外一種實(shí)現(xiàn):

using UnityEngine; using System.Collections;[ExecuteInEditMode] public class MyDungeonCamera : MonoBehaviour {/// [攝像機(jī)控制參數(shù)]public GameObject Target = null;public float RotateX = 0f; // pitch 俯仰public float RotateY = 0f; // yaw 偏航public float Distance = 10f; // 攝像機(jī)遠(yuǎn)近public float MoveSmoothTime = 0.3f; // 位置平滑時(shí)間,默認(rèn)為1spublic float RotateSmoothTime = 0.3f; // 旋轉(zhuǎn)平滑時(shí)間public float ScrollWheelSpeed = 1000f; // 中軸調(diào)整速度public Vector3 TargetOffset = Vector3.zero; // 目標(biāo)偏移量private Vector3 Velocity = Vector3.zero; // 平滑初速度private Vector3 Offset = Vector3.zero; // 根據(jù)上面三個(gè)變量計(jì)算出private const float MinDistance = 5f; // 鏡頭最近距離private const float MaxDistance = 100f; // 鏡頭最遠(yuǎn)距離private Quaternion tmpRotation = Quaternion.identity;private Vector3 tmpPosition = Vector3.zero;private float RotateDamping{get{if (RotateSmoothTime <= 0f) RotateSmoothTime = 0.001f;return 1f / RotateSmoothTime;}}void LateUpdate(){if (Target == null) return;tmpRotation = transform.rotation;tmpPosition = transform.position;UpdateDistance();UpdateRotation();UpdatePosition();transform.rotation = tmpRotation;transform.position = tmpPosition;}private void UpdateRotation(){if (!NeedRotate()) return;Quaternion wantedRotation = Quaternion.Euler(RotateX, RotateY, 0f);// 旋轉(zhuǎn)采用球形插值tmpRotation = Quaternion.Slerp(tmpRotation, wantedRotation, Time.deltaTime * RotateDamping);}private void UpdatePosition(){// 如果有旋轉(zhuǎn)插值,則位置根據(jù)旋轉(zhuǎn)變換;否則,位置自己進(jìn)行插值過渡if (!NeedRotate()){Offset = Quaternion.Euler(RotateX, RotateY, 0f) * Vector3.forward * Distance;Vector3 wantedPos = Target.transform.position - Offset + TargetOffset;// 位置采用平滑阻尼過渡tmpPosition = Vector3.SmoothDamp(tmpPosition, wantedPos, ref Velocity, MoveSmoothTime);}else{Offset = tmpRotation * Vector3.forward * Distance;tmpPosition = Target.transform.position - Offset + TargetOffset;}}private void UpdateDistance(){float horizontal = Input.GetAxis("Mouse ScrollWheel") * ScrollWheelSpeed * Time.deltaTime;Distance -= horizontal;Distance = Mathf.Clamp(Distance, MinDistance, MaxDistance);}private bool NeedRotate(){Vector3 eulerAngles = transform.rotation.eulerAngles;return !(FloatEqual(eulerAngles.x, RotateX) && FloatEqual(eulerAngles.y, RotateY));}public static bool FloatEqual(float value1, float value2){float ret = value1 - value2;return ret > -0.0005f && ret < 0.0005f;}}

  這個(gè)實(shí)現(xiàn)中,有幾點(diǎn)需要注意的:

  (1)rotation使用四元素球形插值,這樣保證每次旋轉(zhuǎn)的角速度是恒定的,不過兩次旋轉(zhuǎn)各自的角速度不相等,這里可以改進(jìn);

  (2)position使用Vector3.SmoothDamp進(jìn)行平滑阻尼過渡效果會(huì)比較好;

  (3)浮點(diǎn)數(shù)相等判斷,不要直接用等號喲;

  (4)當(dāng)同時(shí)有rotation和position時(shí),以rotation為主;

  (5)是否需要旋轉(zhuǎn)的判斷,只有需要的時(shí)候才走旋轉(zhuǎn)邏輯,這樣可以減輕Update的壓力。

  攝像機(jī)振動(dòng)腳本:

public class ShakeCamera : MonoBehaviour {public float ShakeTime = 1f;public float ShakeStrength = 0.2f;private Vector3 ShakeOffset = Vector3.zero;private Vector3 preShakeOffset = Vector3.zero;void LateUpdate(){transform.position = transform.position - preShakeOffset + ShakeOffset;}public void Shake(){StopCoroutine("ShakeCoroutine");StartCoroutine("ShakeCoroutine");}public void Shake(float time){ShakeTime = time;Shake();}IEnumerator ShakeCoroutine(){float endTime = Time.time + ShakeTime;while (Time.time < endTime){ShakeOffset = Random.insideUnitSphere * ShakeStrength;yield return null;}ShakeOffset = Vector3.zero;}}

?

轉(zhuǎn)載于:https://www.cnblogs.com/sifenkesi/p/3994594.html

總結(jié)

以上是生活随笔為你收集整理的各种Camera,总有一款适合你(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。