足場に乗ろう
CoddyのUnityジャーニー「本格的なゲームを作る」セクションの一部。レッスン 51/60。
CharacterController は、その足元にあるものに運ばれません。動くプラットフォームの上ではその場にとどまり、プラットフォームが下を滑って離れていきます。transform.position を動かしても効果はありません。次の Move は、物理演算が最後に認識した位置から始まり、変更が取り消されるからです。
そこで、プレイヤーはプラットフォームの移動量を自身の移動量に加えます。OnControllerColliderHit(ControllerColliderHit hit) は、Move が接触するコライダーごとに実行されます。下からの接触では hit.normal.y は 1 に近い値になります。クレートを同じ方法で運ぶフェリーの例です。
private Ferry ferry;
void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.normal.y > 0.7f && hit.gameObject.TryGetComponent(out Ferry f))
{
ferry = f;
}
}チャレンジ
中級プレイヤーが動くプラットフォームに乗れるようにしましょう。
Playerにprivate MovingPlatform platform;とOnControllerColliderHitを追加します。hit.normal.y > 0.5fで、オブジェクトがMovingPlatformを持っている場合、それをplatformに保持します。Update()で、(move + velocity) * Time.deltaTimeをVector3 motionに入れます。platform != nullの場合は、platform.deltaを加えて、platform = nullを設定します。controller.Move(motion)を呼び出します。
「プレイ」を押してプラットフォームに飛び乗ると、運ばれます。その後、「確認」を押します。
自分で試してみよう
using UnityEngine;
using UnityEngine.InputSystem;
public class Player : MonoBehaviour
{
[SerializeField] private float speed = 5f;
[SerializeField] private float jumpHeight = 1.5f;
[SerializeField] private float gravity = -9.81f;
private CharacterController controller;
private InputAction moveAction;
private InputAction jumpAction;
private Vector3 velocity;
void Start()
{
controller = GetComponent<CharacterController>();
moveAction = InputSystem.actions.FindAction("Move");
jumpAction = InputSystem.actions.FindAction("Jump");
}
void Update()
{
if (controller.isGrounded && velocity.y < 0f)
{
velocity.y = -2f;
}
Vector2 input = moveAction.ReadValue<Vector2>();
Vector3 move = new Vector3(input.x, 0f, input.y) * speed;
if (jumpAction.WasPressedThisFrame() && controller.isGrounded)
{
velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
}
velocity.y += gravity * Time.deltaTime;
controller.Move((move + velocity) * Time.deltaTime);
}
}
本格的なゲームを作るのすべてのレッスン
自分で練習してみよう: Unityプレイグラウンド