我最近一直在使用Unity Engine进行一个项目,该项目涉及一种自上而下的第三人称视图,我在角色移动方面遇到了问题。
我想实现一种方法,让玩家使用WASD移动、点击移动或拖动移动在整个地图上移动,让他们可以在任何时候自由使用这两种移动,但我还没有找到实现这一点的方法,因为这些方法最终会相互抵消,导致玩家角色移动笨拙,并陷入困境。
有什么办法可以做到这一点吗?如果是的话,任何提示/建议都将不胜感激。请记住,当涉及到Unity和C#时,我是一个完全的初学者,所以我可能还没有掌握一些核心概念。
我在下面附上了我的PlayerMovement
C#代码。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(test))]
public class PlayerMovement : MonoBehaviour
{
private test _input;
//click2move
private NavMeshAgent agent;
//x
[SerializeField]
private bool RotateTowardMouse;
[SerializeField]
private float MovementSpeed;
[SerializeField]
private float RotationSpeed;
[SerializeField]
private Camera Camera;
void Start()
{
//c2m
agent = GetComponent<NavMeshAgent>();
//x
}
private void Awake()
{
_input = GetComponent<test>();
}
// Update is called once per frame
void Update()
{
var targetVector = new Vector3(_input.InputVector.x, 0, _input.InputVector.y);
var movementVector = MoveTowardTarget(targetVector);
agent.autoBraking = true;
if (!RotateTowardMouse)
{
RotateTowardMovementVector(movementVector);
}
if (RotateTowardMouse)
{
RotateFromMouseVector();
}
//c2m
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
if (Input.GetMouseButtonDown(0))
{
agent.SetDestination(hit.point);
}
}
else
{
if (agent.remainingDistance < 1)
{
agent.ResetPath();
}
}
}
private void RotateFromMouseVector()
{
Ray ray = Camera.ScreenPointToRay(_input.MousePosition);
if (Physics.Raycast(ray, out RaycastHit hitInfo, maxDistance: 300f))
{
var target = hitInfo.point;
target.y = transform.position.y;
transform.LookAt(target);
}
}
private Vector3 MoveTowardTarget(Vector3 targetVector)
{
var speed = MovementSpeed * Time.deltaTime;
// transform.Translate(targetVector * (MovementSpeed * Time.deltaTime)); Demonstrate why this doesn't work
//transform.Translate(targetVector * (MovementSpeed * Time.deltaTime), Camera.gameObject.transform);
targetVector = Quaternion.Euler(0, Camera.gameObject.transform.rotation.eulerAngles.y, 0) * targetVector;
var targetPosition = transform.position + targetVector * speed;
transform.position = targetPosition;
return targetVector;
}
private void RotateTowardMovementVector(Vector3 movementDirection)
{
if (movementDirection.magnitude == 0) { return; }
var rotation = Quaternion.LookRotation(movementDirection);
transform.rotation = Quaternion.RotateTowards(transform.rotation, rotation, RotationSpeed);
}
}
我强烈建议您使用Unity输入系统。它可以在输入设备之间自动切换,并将代码与任何特定控件解耦。如果你对C#的经验有限,这可能会有点让人不知所措,但你可以依赖大量的教程视频和书面指南。
PlayerInput
组件检测何时添加或移除不同的输入设备,并切换到第一有效控制方案。当用户激活触发游戏中某些内容所需的输入时,即表示为Action
。根据输入的状态调用该操作的一组回调:started
、performed
和canceled
。在这里,您可以将角色控制器连接到输入,并运行将输入转换为移动所需的任何额外逻辑。输入系统还有一个称为交互的功能,它可能很有用,尤其是对于拖动来移动控件。
祝你好运!如果你想让我进一步解释什么,或者给你一个好的教程,请随时在评论中标记我。
首先在场景中创建一个Capsule,将主相机拖动到其对象,将脚本挂在Capsule对象下,WASD控制移动方向,空间沿Y轴向上移动,F沿Y轴向下移动,谢谢
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveCam : MonoBehaviour
{
private Vector3 m_camRot;
private Transform m_camTransform;//Camera Transform
private Transform m_transform;//Camera parent object Transform
public float m_movSpeed=10;//Movement factor
public float m_rotateSpeed=1;//Rotation factor
private void Start()
{
m_camTransform = Camera.main.transform;
m_transform = GetComponent<Transform>();
}
private void Update()
{
Control();
}
void Control()
{
if (Input.GetMouseButton(0))
{
//Get the mouse movement distance
float rh = Input.GetAxis("Mouse X");
float rv = Input.GetAxis("Mouse Y");
// rotate the camera
m_camRot.x -= rv * m_rotateSpeed;
m_camRot.y += rh*m_rotateSpeed;
}
m_camTransform.eulerAngles = m_camRot;
// Make the main character face in the same direction as the camera
Vector3 camrot = m_camTransform.eulerAngles;
camrot.x = 0; camrot.z = 0;
m_transform.eulerAngles = camrot;
// Define 3 values to control movement
float xm = 0, ym = 0, zm = 0;
//Press W on the keyboard to move up
if (Input.GetKey(KeyCode.W))
{
zm += m_movSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.S))//Press keyboard S to move down
{
zm -= m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.A))//Press keyboard A to move left
{
xm -= m_movSpeed * Time.deltaTime;
}
else if (Input.GetKey(KeyCode.D))//Press keyboard D to move right
{
xm += m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.Space) && m_transform.position.y <= 3)
{
ym+=m_movSpeed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.F) && m_transform.position.y >= 1)
{
ym -= m_movSpeed * Time.deltaTime;
}
m_transform.Translate(new Vector3(xm,ym,zm),Space.Self);
}
}