自学了几周unity了,感觉还是要做点什么上手才快,所以先做个简单的RPG游戏吧。然后很快就做出了CS那种第一人称视觉的人物操控,不过感觉体验不太好,不能边走边看周围,所以重新模仿了原神那种可以环绕人物随便转动视觉,人物也可以随意走动的模式。
代码写得可能有点啰嗦,如果有大神知道更好的实现方法,麻烦指教一下,真心感谢
首先把镜头放到人物的身后,然后各自挂上脚本就行了。
CameraControl
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraControl : MonoBehaviour
{
private Transform player;
private Vector3 dir;
// Start is called before the first frame update
void Start()
{
player = GameObject.FindGameObjectWithTag("Player").transform;
dir = player.transform.position - transform.position;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyUp(KeyCode.LeftAlt))
{
Cursor.lockState = Cursor.lockState == CursorLockMode.Locked ? CursorLockMode.None : CursorLockMode.Locked;
}
transform.position = player.transform.position - dir;
if(Input.GetAxis("Mouse ScrollWheel") > 0)
{
transform.Translate(dir/6f, Space.World);
dir = player.transform.position - transform.position;
}
else if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
transform.Translate(-dir/6f, Space.World);
dir = player.transform.position - transform.position;
}
if (Input.GetAxis("Mouse X") != 0f)
{
float mouseX = Input.GetAxis("Mouse X");
transform.RotateAround(player.position, Vector3.up, mouseX * 400 * Time.deltaTime);
dir = player.transform.position - transform.position;
}
if (Input.GetAxis("Mouse Y") != 0f)
{
float mouseY = Input.GetAxis("Mouse Y");
transform.Rotate(Vector3.right, -mouseY * 400 * Time.deltaTime);
}
}
}
PlayerControl
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControl : MonoBehaviour
{
private Animator animator;
private CharacterController characterController;
public float speed = 3.0F;
public float gravity = 20.0F;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
characterController = GetComponent<CharacterController>();
}
private bool IsAcking()
{
return animator.GetCurrentAnimatorStateInfo(0).IsName("Ekard_Attack_01") || animator.GetCurrentAnimatorStateInfo(0).IsName("Ekard_Attack_02");
}
private void DoMove(Vector3 dir)
{
if (!IsAcking())
{
if (characterController.isGrounded)
{
characterController.SimpleMove(dir);
}
else
{
Vector3 d = Vector3.zero;
d.y -= gravity * Time.deltaTime;
characterController.Move(d);
}
}
}
// Update is called once per frame
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
if (horizontal != 0 && vertical != 0) //斜
{
//镜头指向人物的水平向量
Vector3 camToPlayer = new Vector3(transform.position.x - Camera.main.transform.position.x, 0, transform.position.z - Camera.main.transform.position.z);
//与【镜头指向人物的水平向量】垂直的水平向量
Vector3 vTo_CamToPlayer = horizontal > 0 ? GetRightSideVerticalDir(Camera.main.transform.position, transform.position, camToPlayer) : -GetRightSideVerticalDir(Camera.main.transform.position, transform.position, camToPlayer);
//判断向前还是向后
camToPlayer = vertical > 0 ? camToPlayer : -camToPlayer;
//人物最终朝向
Vector3 finalNormalized = (camToPlayer.normalized + vTo_CamToPlayer).normalized;
//人物最终朝向点
Vector3 targetPos = new Vector3(finalNormalized.x + transform.position.x, transform.position.y, finalNormalized.z + transform.position.z);
transform.LookAt(targetPos);
DoMove((targetPos - transform.position) * speed);
}
else if(horizontal != 0 && vertical == 0) //左右
{
Vector3 camToPlayer = new Vector3(transform.position.x - Camera.main.transform.position.x, 0, transform.position.z - Camera.main.transform.position.z);
Vector3 vTo_CamToPlayer = GetRightSideVerticalDir(Camera.main.transform.position, transform.position, camToPlayer);
vTo_CamToPlayer = horizontal > 0 ? vTo_CamToPlayer : -vTo_CamToPlayer;
Vector3 targetPos = new Vector3(vTo_CamToPlayer.x + transform.position.x, transform.position.y, vTo_CamToPlayer.z + transform.position.z);
transform.LookAt(targetPos);
DoMove((targetPos - transform.position) * speed);
}
else if (horizontal == 0 && vertical != 0) //前后
{
Vector3 camToPlayer = new Vector3(transform.position.x - Camera.main.transform.position.x, 0, transform.position.z - Camera.main.transform.position.z);
Vector3 dirNormalized = vertical > 0 ? camToPlayer.normalized : -camToPlayer.normalized;
Vector3 targetPos = new Vector3(dirNormalized.x + transform.position.x, transform.position.y, dirNormalized.z + transform.position.z);
transform.LookAt(targetPos);
DoMove((targetPos - transform.position) * speed);
}
if (horizontal != 0f || vertical != 0f)
{
animator.SetBool("isRun", true);
}
else
{
animator.SetBool("isRun", false);
}
if (Input.GetMouseButtonDown(0))
{
animator.SetBool("isAck", true);
}
else if (Input.GetMouseButtonUp(0))
{
animator.SetBool("isAck", false);
}
}
//获取垂直水平向量(dir的正右边)
public static Vector3 GetRightSideVerticalDir(Vector3 startPos, Vector3 endPos, Vector3 _dir)
{
Vector3 result;
if (_dir.x == 0)
{
result = new Vector3(1, 0, 0);
}
else
{
result = new Vector3(-_dir.z / _dir.x, 0, 1).normalized;
}
//如果终点在起点右上角,即dir指向右上角(在坐标系中)
if(endPos.x > startPos.x && endPos.z > startPos.z)
{
//如果垂直向量指向dir正右边(即指向右下角),那么必然x>0,z<0
if (result.x > 0 && result.z < 0) {
return result;
}
else
{
return -result;
}
}else if(endPos.x > startPos.x && endPos.z < startPos.z)
{
if (result.x < 0 && result.z < 0)
{
return result;
}
else
{
return -result;
}
}
else if (endPos.x < startPos.x && endPos.z > startPos.z)
{
if (result.x > 0 && result.z > 0)
{
return result;
}
else
{
return -result;
}
}
else if (endPos.x < startPos.x && endPos.z < startPos.z)
{
if (result.x < 0 && result.z > 0)
{
return result;
}
else
{
return -result;
}
}
return result;
}
}
|