ざっくり2.5Dの自機移動制御[Unity]

# 目標
2.5D上を動く球を制御するクラスと周辺の設計！

## 目次
1) InputSystem使う
2) rbの数値変更をする
3) 重力変更する


## 本音
もし気が向いたら更新しに、戻りにきます。今は、画像とコードでなんとか理解してみてください。

### InputSystemにMove2Dを追加
ValueとAxisを選択する。
Trigger BehaviorにReleaseを含めることで静止もちゃんと判定する。
![Screenshot 2025-04-25 at 13.59.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4049858/185cb1f0-3925-49b2-842c-ec4363801043.png)

### Bindingを追加
Add positive/negative bindingで2D入力制御する。
筆者はnegativeにAキーを、positiveにDキーを採択。
![Screenshot 2025-04-25 at 13.59.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4049858/27a481b1-f379-449d-b16b-2e217a3a4f0f.png)

### コードを書く
頑張って解釈してみてください。

```c#:SphereControl.cs
/*
 * Copyright (c) DeepNapEngine
 * https://github.com/TrueRyoB
 */
using UnityEngine;
using UnityEngine.InputSystem;
// using System;
// using System.Collections;
// using System.Collections.Generic;

namespace PoseQ.Core.GamePlay.RhyRhyDaDa
{
    /// <summary>
    /// Space key to jump
    /// Side key to move
    /// Kinetic features implemented
    /// </summary>
    public class SphereControl : MonoBehaviour
    {
        #region variables
        
        // references
        [Header("Stats")] 
        [SerializeField] private Rigidbody rb;
        [SerializeField] private InputActionAsset inputActionAsset;
        private InputActionMap _playerActions;
        
        // bool stats
        private bool _onGround;
        private bool _canMove = true;
        private bool _isJumping;
        
        
        // movement stats
        //private readonly float _maxSpeed = 13f;
        //private readonly float _jumpForce = 8f;
        // private readonly float _moveForce = 60f;
        private readonly float _groundCheckDistance = 1.1f;
        [SerializeField] private LayerMask playerMask;
        [SerializeField] private LayerMask groundMask;

        private LayerMask _groundMaskWithoutPlayer;

        private float _inputX;
        
        
        //for adjustment
        [Header("For adjustment")]
        [SerializeField]private float _jumpForce = 15f;
        [SerializeField]private float _maxSpeed = 10f;
        [SerializeField]private float _moveForce = 30f;
        
        #endregion

        #region Event functions
        private void Awake()
        {
            if (rb == null) Debug.LogError("rb is null");
            if (groundMask.value == 0) Debug.LogError("Bad layer");
            
            Physics.gravity = new Vector3(0,-40,0);
            _groundMaskWithoutPlayer = groundMask & ~(1 << playerMask);
        }

        private void FixedUpdate()
        {
            ApplyVelocity();
            CheckGround();
            Debug.DrawRay(transform.position, Vector3.down * _groundCheckDistance, _onGround ? Color.green : Color.red);
        }
        
        private void OnEnable() 
        {
            _playerActions = inputActionAsset.FindActionMap("Player"); 
            _playerActions.Enable(); 
            _playerActions["Move2D"].performed += Move; 
            _playerActions["Jump"].performed += Jump; 
        }
        
        private void OnDisable()
        {
            _playerActions.Disable();
        }
        
        private void OnCollisionEnter(Collision other)
        {
            switch (other.gameObject.tag)
            {
                case Constant.GameObjectTag.RhyRhyDaDa.Spike:
                    // Game Over
                    Debug.LogWarning("Game Over");
                    break;
                case Constant.GameObjectTag.RhyRhyDaDa.Slimy:
                    // Something
                    Debug.LogWarning("Slimy");
                    break;
            }
        }
        #endregion
        
        #region Actions

        private void ApplyVelocity()
        {
            Vector3 input = new Vector3(_inputX, 0, 0);
            
            // input = Camera.main!.transform.TransformDirection(input);
            // input.y = 0f;
            
            rb.AddForce(input.normalized * _moveForce);
            
            Vector3 horizontalVelocity = rb.linearVelocity;
            horizontalVelocity.y = 0f;

            if (horizontalVelocity.magnitude > _maxSpeed)
            {
                Vector3 limitedVelocity = horizontalVelocity.normalized * _maxSpeed;
                rb.linearVelocity = new Vector3(limitedVelocity.x, rb.linearVelocity.y, limitedVelocity.z);
            }
        }
        
        private void Move(InputAction.CallbackContext context) => _inputX = _canMove ? context.ReadValue<float>() : 0f;
        
        private void Jump(InputAction.CallbackContext context)
        {
            _onGround = true;//TODO:layer処理を直す
            if (!_canMove || _onGround) return; 
            
            Vector3 jumpVelocity = rb.linearVelocity;
            jumpVelocity.y = _jumpForce;
            rb.linearVelocity = jumpVelocity;
        }
        #endregion
        
        #region Methods
        private void CheckGround() => 
            _onGround = Physics.Raycast(rb.position, Vector3.down, _groundCheckDistance, _groundMaskWithoutPlayer);
        
        #endregion
    }
}

```

## まとめ
結果を見てみると意外と簡単ですね！数値調整などは自力で頑張ってください。
お疲れ様でした。