注意:我才学几个月的编程,八九成的代码是复制的网上大佬和GPTai的。发布此文章的目的是为了防止以后忘了。
下方代码中,我提前把unity3d中编辑》选项设置》输入管理器里,控制w键和s键的Horizontal轴改名成了WSY,控制a键和d键的Vertical轴改名成了ADY。这段代码上边还写了:
public float moveSpeed = 5;//设立数值移动速度为5
public float rotateSpeed = 30;//设立数值旋转速度为30
public float wsy;//设立数值wsy
public float ady;//设立数值ady
public Rigidbody GangTi;//设立刚体对象gangti
wsy = Input.GetAxis("WSY");//使wsy和输入管理器中的轴有关联
ady = Input.GetAxis("ADY");//使ady和输入管理器中的轴有关联
Rigidbody GangTi = this.gameObject.GetComponent<Rigidbody>();
if (wsy != 0)//如果wsy的值不为0,则向前后移动,方向取决于数值的正负
{
if (GangTi != null)
{
Vector3 targetPos = GangTi.position + GangTi.transform.forward * wsy * moveSpeed * Time.deltaTime;
GangTi.MovePosition(targetPos);
}
BroadcastMessage("TheisMoving","yidong");//发送消息“isMoving”给挂载物体和挂载物体的子物体及其子物体
}
if (ady != 0)//如果ady的值不为0,则向左右移动,方向取决于数值的正负
{
if(GangTi != null)
{
Vector3 targetPos = GangTi.position + GangTi.transform.right * ady * moveSpeed * Time.deltaTime;
GangTi.MovePosition(targetPos);
}
BroadcastMessage("TheisMoving","yidong");//发送消息“isMoving”给挂载物体和挂载物体的子物体及其子物体
}
//这串代码是防止摄像头移动时角色正前方向始终跟随摄像机正前方向
if (wsy == 0 && ady == 0)//如果进退y和左右y的值皆为零,则运行下方逻辑
{
BroadcastMessage("TheisMoving", "Noyidong");//发送消息“NoisMoving”给挂载物体和挂载物体的子物体及其子物体。
}
BroadcastMessage方法来发送消息,是因为我把摄像机脚本所挂载的物体mainCamera放在了人物移动的脚本所挂载的物体之下。也就是说人物是摄像机的父物体。
private bool isMoving = false;//设置布尔值isMoving为否
public void TheisMoving(string message)//接收信号名称为TheisMoving的消息,创建参数message为下方接收参数
{
Debug.Log("AAA");//在Unity3d的控制台输出AAA
if (message == "yidong")//如果参数==yidong,则运行if下方逻辑
{
MovingA();//调用下方的MovingA
}
//这串代码是防止摄像头移动时角色正前方向始终跟随摄像机正前方向
if (message == "Noyidong")//如果参数==Noyidong,则运行if下方逻辑。
{
MovingB();//调用下方的MovingB
}
}
void MovingA()
{
isMoving = true;//修改isMoving的值为是
}
void MovingB()
{
isMoving = false;//修改isMoving的值为否
}
以上就是sendmessage和if语句的联动,接下来放完整代码:
挂载在人物上的脚本,其主要作用是控制移动,number来区分使用哪种移动模式
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playMove : MonoBehaviour
{
public int number = 2;//设立序号number
public float moveSpeed = 5;//设立数值移动速度为5
public float rotateSpeed = 30;//设立数值旋转速度为30
public float wsy;//设立数值wsy
public float ady;//设立数值ady
public Rigidbody GangTi;//设立刚体对象gangti
void Start()
{
}
void Update()
{
if (number == 1) //ws进退,ad旋转
{
wsy = Input.GetAxis("WSY");//使wsy和输入管理器中的轴有关联
ady = Input.GetAxis("ADY");//使ady和输入管理器中的轴有关联
if (wsy != 0)//如果wsy的值不为0,则向前或向后移动,方向取决于数值的正负
{
Rigidbody GangTi = this.gameObject.GetComponent<Rigidbody>();//获得刚体
if (GangTi != null)//刚体不等于空时,执行下方逻辑
{
Vector3 targetPos = GangTi.position + GangTi.transform.forward * wsy * moveSpeed * Time.deltaTime;//
GangTi.MovePosition(targetPos);//
}
BroadcastMessage("TheisMoving","yidong");//发送消息“isMoving”给挂载物体和挂载物体的子物体及其子物体
}
if (ady != 0)//如果ady的值不为0,则向左或向右旋转,方向取决于数值的正负
{
if (wsy < 0)//此代码解决按下SD(右后)实际往左后移动的bug
{
ady = -ady;//
}
Vector3 rotateValue = Vector3.up * ady * rotateSpeed * Time.deltaTime;//
this.transform.Rotate(rotateValue);//
}
}
if (number == 2)//wasd是四向移动
{
wsy = Input.GetAxis("WSY");//使wsy和输入管理器中的轴有关联
ady = Input.GetAxis("ADY");//使ady和输入管理器中的轴有关联
Rigidbody GangTi = this.gameObject.GetComponent<Rigidbody>();
if (wsy != 0)//如果wsy的值不为0,则向前后移动,方向取决于数值的正负
{
if (GangTi != null)
{
Vector3 targetPos = GangTi.position + GangTi.transform.forward * wsy * moveSpeed * Time.deltaTime;
GangTi.MovePosition(targetPos);
}
BroadcastMessage("TheisMoving","yidong");//发送消息“isMoving”给挂载物体和挂载物体的子物体及其子物体
}
if (ady != 0)//如果ady的值不为0,则向左右移动,方向取决于数值的正负
{
if(GangTi != null)
{
Vector3 targetPos = GangTi.position + GangTi.transform.right * ady * moveSpeed * Time.deltaTime;
GangTi.MovePosition(targetPos);
}
BroadcastMessage("TheisMoving","yidong");//发送消息“isMoving”给挂载物体和挂载物体的子物体及其子物体
}
//这串代码是防止摄像头移动时角色正前方向始终跟随摄像机正前方向
if (wsy == 0 && ady == 0)//如果进退y和左右y的值皆为零,则运行下方逻辑
{
BroadcastMessage("TheisMoving", "Noyidong");//发送消息“NoisMoving”给挂载物体和挂载物体的子物体及其子物体。
}
}
}
}
下面是挂载在摄像机上的脚本,其作用就是充当视角
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour
{
public int mode = 1;//设立int值mode等于1,这个值是为了给下文切换视角模式准备用
public Transform targetCameraPosition;//设立转换targetCameraPositon,使之可以在unity检查器界面中选择摄像机对象
public Vector3 mode1xyz = new Vector3(0, 5, -7);//设立3d位置mode1xyz = (0,5,7)
public Vector3 mode2xyz = new Vector3(0, (float)3.5, (float)0.5);//设立3d位置mode2xyz = (0,2.5f,0.5f)
// 水平视角移动的敏感度
public float sensitivityHor = 3f;
// 垂直视角移动的敏感度
public float sensitivityVer = 3f;
// 视角向上移动的角度范围,该值越小范围越大
public float upVer = -90; //(在Unity的坐标轴中+z为正前方、-z为正后方。)围绕x轴向下旋转负90度
// 视角向下移动的角度范围,该值越大范围越大
public float downVer = 60;//(在Unity的坐标轴中+z为正前方、-z为正后方。)围绕x轴向下旋转90度
// 垂直旋转角度
private float rotVer;
public Transform target; //相机追随的目标
public float xSpeed = 200; //X轴方向拖动速度
public float ySpeed = 200; //Y轴方向拖动速度
public float mSpeed = 10; //放大缩小速度
public float yMinLimit = -50; //在Y轴最小移动范围
public float yMaxLimit = 50; //在Y轴最大移动范围
public float distance = 10; //相机视角距离
public float minDinstance = 2; //相机视角最小距离
public float maxDinstance = 30; //相机视角最大距离
public float x = 0.0f;//
public float y = 0.0f;//
public float damping = 5.0f;//
public bool needDamping = true;//
public GameObject juese;//设立游戏对象角色
private Camera mainCamera;//私设立摄像机mainCamera
private bool isMoving = false;//设置布尔值isMoving为否
public float cameramode3time;//设立摄像机模式三的镜头切换时间(不赋值)
public void TheisMoving(string message)//接收信号名称为TheisMoving的消息,创建参数message为下方接收参数
{
Debug.Log("AAA");//在Unity3d的控制台输出AAA
if (message == "yidong")//如果参数==yidong,则运行if下方逻辑
{
MovingA();//调用下方的MovingA
}
//这串代码是防止摄像头移动时角色正前方向始终跟随摄像机正前方向
if (message == "Noyidong")//如果参数==Noyidong,则运行if下方逻辑。
{
MovingB();//调用下方的MovingB
}
}
void Start()
{
// 初始化当前的垂直角度
rotVer = transform.eulerAngles.x;
Vector3 angle = transform.eulerAngles;
x = angle.y;
y = angle.x;
mainCamera = Camera.main;//设置摄像机mainCamera = Camera.main
}
void Update()
{
Vector3 cameraForward = mainCamera.transform.forward;//设置Vector3的值名为cameraForward,等于mainCamera的transform的正方向
cameramode3time++;//让cameramode3time每帧自增。
if(mode == 1)//如果mode==1,就执行if下方逻辑
{
Debug.Log("mode=1");//在控制台输出mode=1
targetCameraPosition.localPosition = mode1xyz; //修改目标摄像头的位置为mode2xyz
// 获取鼠标上下的移动位置
float mouseVer = Input.GetAxis("Mouse Y");//使mouseVer和输入管理器中的轴有关联
// 获取鼠标左右的移动位置
float mouseHor = Input.GetAxis("Mouse X");//使mouseHor和输入管理器中的轴有关联
// 鼠标往上移动,视角其实是往下移,所以要想达到视角也往上移的话,就要减去它
rotVer -= mouseVer * sensitivityVer;
// 限定上下移动的视角范围,即垂直方向不能360度旋转
rotVer = Mathf.Clamp(rotVer, upVer, downVer);
// 设置视角的移动值
transform.localEulerAngles = new Vector3(rotVer, 0, 0); // 控制摄像机的上下视角移动(玩家不动)
transform.parent.Rotate(Vector3.up * mouseHor); // 转动玩家的水平视角移动(摄像机也会动)(父物体仅往上一层,不会联动更多层的父物体)
//按F5切换mode
if (Input.GetKeyDown(KeyCode.F5))//如果期间按下了按键F5,就执行下方逻辑
{
mode=2;//修改mode值为2
}
}
else if(mode == 2)//如果mode==2,就执行else if下方逻辑
{
Debug.Log("mode=2");//在控制台输出mode=2
targetCameraPosition.localPosition = mode2xyz;//修改目标摄像头的位置为mode2xyz
SwitchCamera();//引用下文中的代码
UpdateCameraAngle();//引用下文中的代码
//按F5切换mode
if (Input.GetKeyDown(KeyCode.F5))//如果期间按下了按键F5,就执行下方逻辑
{
mode = 3;//修改mode值为3
}
}
else if(mode == 3)//如果mode==3,就执行else if下方逻辑
{
Debug.Log("mode=3");//在控制台输出mode=3
if (target)
{
x += Input.GetAxis("Mouse X") * xSpeed * 0.05f;
y -= Input.GetAxis("Mouse Y") * ySpeed * 0.05f;
y = ClamAngle(y, yMinLimit, yMaxLimit);
distance -= Input.GetAxis("Mouse ScrollWheel") * mSpeed;
distance = Mathf.Clamp(distance, minDinstance, maxDinstance);
Quaternion rotation = Quaternion.Euler(y, x, 0.0f);
Vector3 disVector = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * disVector + target.position;
if (needDamping)
{
transform.rotation = Quaternion.Lerp(transform.rotation, rotation, Time.deltaTime * damping);
transform.position = Vector3.Lerp(transform.position, position, Time.deltaTime * damping);
}
else
{
transform.rotation = rotation;
transform.position = position;
}
}
if (isMoving)
{
if (cameramode3time > 5)//如果cameramode3time的值大于5,就执行下方逻辑
{
cameramode3time = 0;//清空cameramode3time的值为零
juese.transform.forward = cameraForward;//使得角色正前方向变成摄像机正前方向
}
}
if (Input.GetKeyDown(KeyCode.F5))//如果期间按下了按键F5,就执行下方逻辑
{
mode = 1;//修改mode值为1
}
}
}
void SwitchCamera()
{
float mouseVer = Input.GetAxis("Mouse Y");
float mouseHor = Input.GetAxis("Mouse X");
rotVer -= mouseVer * sensitivityVer;
rotVer = Mathf.Clamp(rotVer, upVer, downVer);
transform.localEulerAngles = new Vector3(rotVer, 0, 0);
transform.parent.Rotate(Vector3.up * mouseHor);
}
void UpdateCameraAngle()
{
if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0)
{
Vector3 rotateAroundParent = new Vector3(0, Input.GetAxis("Mouse X"), 0);
Vector3 rotateAroundLocal = new Vector3(0, Input.GetAxis("Mouse Y"), 0);
transform.parent.Rotate(rotateAroundParent);
transform.Rotate(rotateAroundLocal);
}
}
static float ClamAngle(float angle, float min, float max)
{
if (angle < -360)
{
angle += 360;
}
if (angle > 360)
{
angle -= 360;
}
return Mathf.Clamp(angle, min, max);
}
void MovingA()
{
isMoving = true;//修改isMoving的值为是
}
void MovingB()
{
isMoving = false;//修改isMoving的值为否
}
}
没有写注释的地方就是我看不懂的内容了。还有一点,关于摄像机的mode==3时,移动时晃动视角会导致摄像机疯狂晃动抽搐,但是除此之外要求的都达到了,所以我暂时就不修复这个问题了,如果后来解决的话就放在评论区。