- Smooth系とLerp系について
- Mathfについての解説(参考)
- unity smoothdamp vs lerp(参考)
- smoothは曲線補間、lerpは線形補間とのこと
- Unity側はsmoothdampを想定している(参考)
- 処理を行うUpdateの種類について
- まずは基本のおさらい(公式:イベント関数の実行順)
- この情報自体が正しくないという話もあるので、あくまで基本
- この図を見るとUpdate前に必ずFixedUpdateが呼ばれているように見えるが、FixedUpdateは固定フレームの物理演算用のUpdateなので通常のUpdateとは非同期
- RigidBodyの処理はFixedUpdateで行う(参考)
- このことはFixedUpdateのリファレンスにも書いてある(参考)
- カメラの追従はLateUpdate推奨(参考)
- 低速での追従でどうしてもガタツキがでる現象について
- FPSを意図的に落としてFixedUpdateで呼び出す(参考)
今回、ロボットの頭に追従するカメラを作成したが、最終的に次のようにした。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using System.Collections; | |
public class FollowingCocpit_2 : MonoBehaviour { | |
private Transform _followedTarget;//<! 追従対象 | |
private Transform _cockpitPosTra;//<! コクピット収納位置 | |
private Transform _dummyTarget;//<! 追従対象のダミー(ダメージモーション等のとき、本来の頭の位置に設置する) | |
private Transform _player; | |
private float _t = 0f; | |
[SerializeField] private float _limitRot = 0f; | |
[SerializeField] private float _accelerationInLimitRot = 5f; | |
[SerializeField] private float _rotSpeed = 1f; | |
[SerializeField] private float _posSpeed = 0.3f; | |
void Start() | |
{ | |
// プレイヤーからアクセスできるよう自身を登録 | |
_player = GameObject.FindWithTag("Player").transform; | |
_player.GetComponent<MSManager>().SetCockpitFollowing(this); | |
// コクピット収納位置 | |
_cockpitPosTra = _player.GetComponent<MSManager>().msData.GetCockpitPositionTransform(); | |
transform.position = _cockpitPosTra.position; | |
// 最初はコクピット収納位置に追従 | |
_followedTarget = _cockpitPosTra; | |
//ダミーを複製しておく | |
_dummyTarget = Object.Instantiate(_cockpitPosTra.gameObject).transform; | |
_dummyTarget.name = _cockpitPosTra.gameObject.name + " Dummy"; | |
JoinToRealHead(); | |
} | |
void Update() | |
{ | |
if (_followedTarget == null) return; | |
ControlRotation(); | |
ControlPosition();//アニメーション適用後なので、IKにより位置が変わると差異が生まれる | |
Debug.DrawLine(_dummyTarget.position, _followedTarget.position,Color.red); | |
} | |
void ControlPosition() | |
{ | |
if (transform.position == _cockpitPosTra.position && _t == 1) return; | |
_t = Mathf.Clamp01(_t + Time.deltaTime * _posSpeed); | |
Debug.Log(_t); | |
Vector3 goal = Vector3.Lerp(_dummyTarget.position, _cockpitPosTra.position, _t);//_dummyTarget.position が _cockpitPosTra.positionと同値の場合、_tは無関係 | |
transform.position = goal; | |
} | |
void ControlRotation() | |
{ | |
//回転の追従 | |
float angle = Quaternion.Angle(transform.rotation, _followedTarget.rotation); | |
float amp = 1 + Mathf.InverseLerp(_limitRot, 180, angle) * _accelerationInLimitRot; | |
transform.rotation = Quaternion.Slerp(transform.rotation, _followedTarget.rotation, Time.deltaTime * _rotSpeed * amp); | |
} | |
//! Animatorから呼び出す | |
public void LeaveFromRealHead() | |
{ | |
_t = 0; | |
if (_followedTarget == _dummyTarget) return; | |
Debug.Log("Leave"); | |
//! 呼ばれた時点での頭の座標と向きをコピー | |
_dummyTarget.position = _cockpitPosTra.position; | |
_dummyTarget.rotation = _cockpitPosTra.rotation; | |
//親を変える | |
_dummyTarget.parent = _player.transform; | |
//! 追従対象を変える | |
_followedTarget = _dummyTarget; | |
} | |
//! Animatorから呼び出す | |
public void JoinToRealHead() | |
{ | |
Debug.Log("Join"); | |
//! 呼ばれた時点での頭の座標と向きをコピー | |
_dummyTarget.position = _cockpitPosTra.position; | |
_dummyTarget.rotation = _cockpitPosTra.rotation; | |
//親を変える | |
_dummyTarget.parent = _cockpitPosTra.transform; | |
//! 追従対象を変える | |
_followedTarget = _cockpitPosTra; | |
} | |
} |