【ダークソウル風ゲームを作りたい(Unity)。その3】

今回はカメラとプレイヤーの間にオブジェクトがある場合、カメラをオブジェクトよりも内側に移動するようにします。
これにより、オブジェクトに遮られてプレイヤーがカメラに映らなくなることを防ぎます。

youtu.be

・下記スクリプトを追加します。

 public class CameraHandler : MonoBehaviour //+EP2 cameraHolderにアタッチ
    {
      (省略)
        private Vector3 cameraFollowVelocity = Vector3.zero; //+EP3

        private float targetPosition; //+EP3
        
        public float cameraSphereRadius = 0.2f; //+EP3 球体レイの半径
        public float cameraCollisionOffset = 0.2f; //+EP3 カメラ位置のオフセット
        public float minimumCollisionOffset = 0.2f; //+EP3 カメラとプレイヤーの最小距離

//+EP3 カメラとプレイヤーの間にオブジェクトがある場合、カメラをオブジェクトよりも内側に移動
        private void HandleCameraCollisions(float delta)
        {
            targetPosition = defaultPosition; //MainCameraLocalPosion.z
            RaycastHit hit;
            //プレイヤーからMainCameraへのベクトル
            Vector3 direction = cameraTransform.position - cameraPivotTransform.position;
            direction.Normalize();

            //Physics.SphereCast (Vector3 origin, float radius, Vector3 direction, out RaycastHit hitInfo,
            //float maxDistance= Mathf.Infinity, int layerMask= DefaultRaycastLayers,
            //球体のレイを飛ばし、オブジェクトコライダーの付いたオブジェクトがヒットするかを調べ、ヒットしたらtrueを返す
            //origin:球形が通過を開始する地点の中心 radius:球の半径 direction:球を通過させる方向
            //hitInfo:If true is returned, hitInfo will contain more information about where the collider was hit. (See Also: RaycastHit).
            //maxDistance:キャストの最大の長さ
            //layerMask:レイヤーマスク はレイキャストするときに選択的に衝突を無視するために使用します。

            //MainCameraとプレイヤーの間のオブジェクト有無を判定
            //CameraPivot位置(=プレイヤー位置)から半径cameraSphereRadiusの球をdirection方向(プレイヤーからMainCamera)へ
            //プレイヤー~MainCameraの距離飛ばす。
            if (Physics.SphereCast(cameraPivotTransform.position,cameraSphereRadius,direction,
                out hit,Mathf.Abs(targetPosition),ignoreLayers))
            {
                //オブジェクトがヒットした場合
                //変数disにcameraPivotTransform.positionとヒットオブジェクトの距離を格納
                float dis = Vector3.Distance(cameraPivotTransform.position, hit.point);

                //求めたdisからオフセット値を引く。おそらくカメラ位置をオブジェクトよりも内側にする為。
                targetPosition = -(dis - cameraCollisionOffset);
            }

            //targetPositionがminimumCollisionOffsetより小さい場合
            if (Mathf.Abs(targetPosition) < minimumCollisionOffset)
            {
                //カメラが近くなりすぎるので、一定の距離をとる
                targetPosition = -minimumCollisionOffset;
            }

            //MainCameraのz位置をtargetPositionに近づける
            cameraTransformPosition.z = Mathf.Lerp(cameraTransform.localPosition.z, targetPosition, delta / 0.2f);
            cameraTransform.localPosition = cameraTransformPosition;
        }
}

今回は以上です。