AngryBotResources/Prefabs/Player을 씬뷰로 끌어다 놓는다.

Player와 Main Camera의 transform을 다음과 같이 조정한다.

 

Player Prefab은 이미 Character Controller컴포넌트가 이미 설정되어 있고 실행하면  Idle 애니메이션을 취하고 있다.

 

주인공 캐릭터 이동및 회전

프로젝트뷰에서 Scripts폴더안에 새로운 스크립트를 하나 만들고 이름을 Movement로 변경한다. 작성후 Player에 적용한다.

Player의 이동처리는 CharacterController의 SimpleMove함수를 이용한다.

        // 주인공 캐릭터 이동처리
        controller.SimpleMove(moveDir * moveSpeed);

Plane객체는 지정한 지점에 가상의 바닥을 생성한다.

        // 가상의 바닥을 주인공의 위치를 기준으로 생성
        plane = new Plane(transform.up, transform.position);

Turn() 함수에서는 ScreenPointToRay 함수를 이용해 마우스 커서의 위치값을 이용해 Ray를 생성한다.

        // 마우스의 2차원 좌푯값을 이용해 3차원 광선(레이)를 생성
        ray = camera.ScreenPointToRay(Input.mousePosition);

생성된 ray는 Plane.Raycast를 사용해 가상의 바닥으로 광선을 투사해 Ray.GetPoint로 닿은 지점을 계산한다.

// 가상의 바닥에 레이를 발사해 충돌한 지점의 거리를 enter 변수로 반환
plane.Raycast(ray, out enter);
// 가상의 바닥에 레이가 충돌한 좌푯값 추출
hitPoint = ray.GetPoint(enter);

가상의 바닥과 닿은 지점과 Player의 위치를 차이는 회전해야할 방향벡터이고 마우스 커서가 있는 지점으로 회전하게 된다.

// 회전해야 할 방향의 벡터를 계산
Vector3 lookDir = hitPoint - transform.position;
lookDir.y = 0;
// 주인공 캐릭터의 회전값 지정
transform.localRotation = Quaternion.LookRotation(lookDir);

이 방법은 가상의 바닥의 충돌지점을 얻어 오기 때문에 지상의 구조물을 포인팅하면 엉뚱한 곳으로 돈다.

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Movement : MonoBehaviour {
    // 컴포넌트 캐시 처리를 위한 변수
    private CharacterController controller;
    private new Transform transform;
    private Animator animator;
    private new Camera camera;

    // 가상의 Plane에 레이캐스팅하기 위한 변수
    private Plane plane;
    private Ray ray;
    private Vector3 hitPoint;

    // 이동 속도
    public float moveSpeed = 10.0f;

    void Start() {
        controller = GetComponent<CharacterController>();
        transform = GetComponent<Transform>();
        animator = GetComponent<Animator>();
        camera = Camera.main;

        // 가상의 바닥을 주인공의 위치를 기준으로 생성
        plane = new Plane(transform.up, transform.position);
    }

    void Update() {
        // 자신이 생성한 네트워크 객체만 컨트롤
            Move();
            Turn();
    }

    // 키보드 입력값 연결
    float h => Input.GetAxis("Horizontal");
    float v => Input.GetAxis("Vertical");

    // 이동 처리하는 함수
    void Move() {
        Vector3 cameraForward = camera.transform.forward;
        Vector3 cameraRight = camera.transform.right;
        cameraForward.y = 0.0f;
        cameraRight.y = 0.0f;

        // 이동할 방향 벡터 계산
        Vector3 moveDir = (cameraForward * v) + (cameraRight * h);
        moveDir.Set(moveDir.x, 0.0f, moveDir.z);

        // 주인공 캐릭터 이동처리
        controller.SimpleMove(moveDir * moveSpeed);

        // 주인공 캐릭터의 애니메이션 처리
        float forward = Vector3.Dot(moveDir, transform.forward);
        float strafe = Vector3.Dot(moveDir, transform.right);

        animator.SetFloat("Forward", forward);
        animator.SetFloat("Strafe", strafe);
    }

    // 회전 처리하는 함수
    void Turn() {
        // 마우스의 2차원 좌푯값을 이용해 3차원 광선(레이)를 생성
        ray = camera.ScreenPointToRay(Input.mousePosition);

        float enter = 0.0f;

        // 가상의 바닥에 레이를 발사해 충돌한 지점의 거리를 enter 변수로 반환
        plane.Raycast(ray, out enter);
        // 가상의 바닥에 레이가 충돌한 좌푯값 추출
        hitPoint = ray.GetPoint(enter);

        // 회전해야 할 방향의 벡터를 계산
        Vector3 lookDir = hitPoint - transform.position;
        lookDir.y = 0;
        // 주인공 캐릭터의 회전값 지정
        transform.localRotation = Quaternion.LookRotation(lookDir);
    }
}

 

+ Recent posts