facebook twitter hatena line email

「Unity/3d/キャラクタ移動」の版間の差分

提供: 初心者エンジニアの簡易メモ
移動: 案内検索
(進むキャラクタの回転方向を固定)
 
(同じ利用者による、間の8版が非表示)
行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.6f, 0.8f) * m_currentV + new Vector3(1.0f, 0.0f, -0.1f) * m_currentH;
+
</pre>
+

2023年2月15日 (水) 11:35時点における最新版

unity/3d/キャラクタ移動/上下左右

unity/3d/キャラクタ移動/前後回転

unity/3d/キャラクタ移動/前後回転_CharacterController

unity/3d/キャラクタ移動/段差乗越_CharacterController