|
|
(同じ利用者による、間の7版が非表示) |
行1: |
行1: |
− | ==キャラクタ移動==
| + | [[unity/3d/キャラクタ移動/上下左右]] |
− | 適当にUnityAssetsからキャラクタをDLする(例:Supercyan Character Pack Free Sample https://assetstore.unity.com/packages/3d/characters/humanoids/character-pack-free-sample-79870?locale=ja-JP)
| + | |
| | | |
− | ===サンプル===
| + | [[unity/3d/キャラクタ移動/前後回転]] |
− | キーボードの上下左右で操作できるサンプル。
| + | |
| | | |
− | CharacterControl.cs
| + | [[unity/3d/キャラクタ移動/前後回転_CharacterController]] |
− | <pre>
| + | |
− | using System.Collections.Generic;
| + | |
− | using UnityEngine;
| + | |
| | | |
− | public class CharacterControl : MonoBehaviour
| + | [[unity/3d/キャラクタ移動/段差乗越_CharacterController]] |
− | {
| + | |
− | [SerializeField] private float m_moveSpeed = 2;
| + | |
− | [SerializeField] private float m_turnSpeed = 200;
| + | |
− | [SerializeField] private float m_jumpForce = 4;
| + | |
− | | + | |
− | [SerializeField] private Animator m_animator = null;
| + | |
− | [SerializeField] private Rigidbody m_rigidBody = null;
| + | |
− | | + | |
− | private float m_currentV = 0;
| + | |
− | private float m_currentH = 0;
| + | |
− | | + | |
− | private readonly float m_interpolation = 10;
| + | |
− | private readonly float m_runScale = 2f;
| + | |
− | | + | |
− | private Vector3 m_currentDirection = Vector3.zero;
| + | |
− | | + | |
− | private bool m_jumpInput = false;
| + | |
− | | + | |
− | private bool m_isGrounded;
| + | |
− | | + | |
− | private List<Collider> m_collisions = new List<Collider>();
| + | |
− | | + | |
− | private void Awake()
| + | |
− | {
| + | |
− | if (!m_animator) { gameObject.GetComponent<Animator>(); }
| + | |
− | if (!m_rigidBody) { gameObject.GetComponent<Animator>(); }
| + | |
− | }
| + | |
− | | + | |
− | private void OnCollisionEnter(Collision collision)
| + | |
− | {
| + | |
− | ContactPoint[] contactPoints = collision.contacts;
| + | |
− | for (int i = 0; i < contactPoints.Length; i++)
| + | |
− | {
| + | |
− | if (Vector3.Dot(contactPoints[i].normal, Vector3.up) > 0.5f)
| + | |
− | {
| + | |
− | if (!m_collisions.Contains(collision.collider))
| + | |
− | {
| + | |
− | m_collisions.Add(collision.collider);
| + | |
− | }
| + | |
− | m_isGrounded = true;
| + | |
− | }
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | private void OnCollisionStay(Collision collision)
| + | |
− | {
| + | |
− | ContactPoint[] contactPoints = collision.contacts;
| + | |
− | bool validSurfaceNormal = false;
| + | |
− | for (int i = 0; i < contactPoints.Length; i++)
| + | |
− | {
| + | |
− | if (Vector3.Dot(contactPoints[i].normal, Vector3.up) > 0.5f)
| + | |
− | {
| + | |
− | validSurfaceNormal = true; break;
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | if (validSurfaceNormal)
| + | |
− | {
| + | |
− | m_isGrounded = true;
| + | |
− | if (!m_collisions.Contains(collision.collider))
| + | |
− | {
| + | |
− | m_collisions.Add(collision.collider);
| + | |
− | }
| + | |
− | }
| + | |
− | else
| + | |
− | {
| + | |
− | if (m_collisions.Contains(collision.collider))
| + | |
− | {
| + | |
− | m_collisions.Remove(collision.collider);
| + | |
− | }
| + | |
− | if (m_collisions.Count == 0) { m_isGrounded = false; }
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | private void OnCollisionExit(Collision collision)
| + | |
− | {
| + | |
− | if (m_collisions.Contains(collision.collider))
| + | |
− | {
| + | |
− | m_collisions.Remove(collision.collider);
| + | |
− | }
| + | |
− | if (m_collisions.Count == 0) { m_isGrounded = false; }
| + | |
− | }
| + | |
− | | + | |
− | private void Update()
| + | |
− | {
| + | |
− | if (!m_jumpInput && Input.GetKey(KeyCode.Space))
| + | |
− | {
| + | |
− | m_jumpInput = true;
| + | |
− | }
| + | |
− | }
| + | |
− | | + | |
− | private void FixedUpdate()
| + | |
− | {
| + | |
− | m_animator.SetBool("Grounded", m_isGrounded);
| + | |
− | DirectUpdate();
| + | |
− | m_wasGrounded = m_isGrounded;
| + | |
− | m_jumpInput = false;
| + | |
− | }
| + | |
− | | + | |
− | private void DirectUpdate()
| + | |
− | {
| + | |
− | float v = Input.GetAxis("Vertical");
| + | |
− | float h = Input.GetAxis("Horizontal");
| + | |
− | | + | |
− | Transform camera = Camera.main.transform;
| + | |
− | | + | |
− | v *= m_runScale;
| + | |
− | h *= m_runScale;
| + | |
− | | + | |
− | m_currentV = Mathf.Lerp(m_currentV, v, Time.deltaTime * m_interpolation);
| + | |
− | m_currentH = Mathf.Lerp(m_currentH, h, Time.deltaTime * m_interpolation);
| + | |
− | | + | |
− | Vector3 direction = camera.forward * m_currentV + camera.right * m_currentH;
| + | |
− | | + | |
− | float directionLength = direction.magnitude;
| + | |
− | direction.y = 0;
| + | |
− | direction = direction.normalized * directionLength;
| + | |
− | | + | |
− | if (direction != Vector3.zero)
| + | |
− | {
| + | |
− | m_currentDirection = Vector3.Slerp(m_currentDirection, direction, Time.deltaTime * m_interpolation);
| + | |
− | | + | |
− | transform.rotation = Quaternion.LookRotation(m_currentDirection);
| + | |
− | transform.position += m_currentDirection * m_moveSpeed * Time.deltaTime;
| + | |
− | | + | |
− | m_animator.SetFloat("MoveSpeed", direction.magnitude);
| + | |
− | }
| + | |
− | }
| + | |
− | }
| + | |
− | </pre>
| + | |
− | | + | |
− | ==進むキャラクタの回転方向を固定==
| + | |
− | <pre>
| + | |
− | // transform.rotation = Quaternion.LookRotation(m_currentDirection); | + | |
− | transform.rotation = Quaternion.Euler(0, 90f, 0f);
| + | |
− | | + | |
− | // カメラの方向を固定。
| + | |
− | // Vector3 direction = camera.forward * m_currentV + camera.right * m_currentH;
| + | |
− | Vector3 direction = new Vector3(0.1f, -0.1f, 1f) * m_currentV + new Vector3(1f, 0f, -0.1f) * m_currentH;
| + | |
− | </pre>
| + | |