一、简介
1、人物部分
a、人物移动
b、镜头旋转
c、玩家开枪:动画、音频、枚举、弹孔、倍镜
2、敌人部分
a、敌人克隆
b、走向玩家:距离,方向、朝向、点乘、叉乘
二、人物部分
(1)、人物移动
CharacterController c;//角色控制器
Vector3 moveDirection = Vector3.zero;//移动方向
float moveSpeed = 6, jumpSpeed = 4;
float gravity = 20;
void Start()
{
c = GetComponent<CharacterController>();
}
void Update()
{
if (c.isGrounded)
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
//固定坐标的前后左右移动
//direction = new Vector3(h, 0, v);
//第一人称移动,normalized表示长度1
moveDirection = (transform.right * h + transform.forward * v).normalized;
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
//一直有一个重力加速度
moveDirection.y -= gravity * Time.deltaTime;
c.Move(moveDirection * moveSpeed * Time.deltaTime);
}
谈谈Move和SimpleMove
1、SimpleMove
SimpleMove 只能在平面移动,不带Y轴移动
移动自带速度。所以不需要乘以Time.deltaTime
移动时自带重力
2、Move
移动方向没有限制
移动时候需要乘以Time.deltaTime
需要自己做重力
在(1)中单有第一人称移动的代码还不行,还需要通过鼠标控制人物方向,才能体现为第一人称移动。
(2)、镜头旋转(人物面向方向,脚本挂在人物上)
Vector3 cameraRotate;
float rotateSpeed = 3f;
void Update () {
//获取鼠标水平和竖直方向的偏移量
float x = Input.GetAxis("Mouse X");
float y = Input.GetAxis("Mouse Y");
//左右旋转(绕Y轴旋转);
cameraRotate.x -= y * rotateSpeed;
//抬头低头(绕X轴旋转)
cameraRotate.y += x * rotateSpeed;
//抬头低头范围
cameraRotate.x = Mathf.Clamp(cameraRotate.x, -45, 45);
//左右旋转范围(CS人物是可以左右无限制旋转的,所以这里可以去掉)
//cameraRotate.y = Mathf.Clamp(cameraRotate.x,-90,90);
transform.rotation = Quaternion.Euler(cameraRotate.x, cameraRotate.y, 0);
}
为了更好的移动,可以试着鼠标隐藏
Cursor.lockState = CursorLockMode.Locked;
(3)、玩家开枪
Transform pos;//枪口位置
private GameObject explosionFx;//爆炸特效
private AudioClip explosionAudios, fireAudios;//爆炸音频,开枪音频
void Start()
{
//动态加载资源(路径: Assets/Resources/Prefabs/HitBlood)
explosionFx = Resources.Load<GameObject>("Prefabs/HitBlood");
explosionAudios = Resources.Load<AudioClip>("Audios/boom");
fireAudios = Resources.Load<AudioClip>("Audios/shoot");
}
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
//点击左键,枪口位置发出开枪音频(自动消失)音量1
AudioSource.PlayClipAtPoint(fireAudios, pos.position, 1f);
RaycastHit hit;//碰撞信息
//检测射线(枪口位置,人物向前方向,碰撞信息,距离20米)
if (Physics.Raycast(pos.position, transform.forward, out hit, 20))
{
GameObject go = Instantiate(explosionFx, hit.point, Quaternion.identity);
Destroy(go, 1f);
//播放爆炸特效(自动消失),音量1
AudioSource.PlayClipAtPoint(explosionAudios, hit.point, 1f);
Destroy(hit.collider.gameObject);
}
}
}
注意:
(a)、cs应该用射线发射,由于要实现倍镜(我没法用准星对齐),最后我选择用摄像机中心发射,而非枪口发射
(b)、开枪时需要有开枪动画
//方法:
Animation an;//动画
void Start()
{
an.GetComponent<Animation>();
}
//an.play("动画名");
an.play("Fire2");
©、音频
public class ResManage
{
//该类的目的是为了存储字符串,简洁其他类
//声音路径
public const string walk = "Sounds/playWalk";//走路声音
public const string run = "Sounds/playRun";//跑步声音
}
AudioClip landClip, runClip;//音频片段
AudioSource audios;//音频组件
void Start()
{
//音频资源
audios = GetComponent<AudioSource>();
//动态加载资源,(体现ResManage类的目的)
landClip = Resources.Load<AudioClip>(ResManage.walk);
runClip = Resources.Load<AudioClip>(ResManage.run);
}
(d)枚举的应用
播放动画时,通常都是用枚举来写(此处写敌人的动画)
enum States
{
Idle,
Run,
Death,
Attack
};
void GetStates(States s)
{
switch (s)
{
case States.Idle:
an.Play(ResManage.nurseIdle);
break;
case States.Run:
an.Play(ResManage.nurseRun);
break;
case States.Death:
an.Play(ResManage.nurseDeath);
break;
case States.Attack:
an.Play(ResManage.nurseAttack);
break;
default:
break;
}
}
用法:GetStates(States.Idle);
(e)、弹孔位置
if (Physics.Raycast(ray, out hit, 100))//摄像机发射
{
if (hit.collider.CompareTag("Plane"))
{
//子弹打洞
//打到地板克隆弹孔
GameObject go = Instantiate(holeEffect, hit.point, holeEffect.transform.rotation);
//让弹孔与射线碰撞体的法线垂直(让弹孔总是贴在碰撞体表面)
go.transform.LookAt(hit.point - hit.normal);
//让弹孔与碰撞体表面保持0.03距离(这里看着合适就行)
go.transform.Translate(Vector3.back * 0.03f);
Destroy(go, 1f);
}
}
(f)、倍镜(减表示放大倍数)
camera.GetComponent().fieldOfView-=45;
三、敌人部分
(1)、克隆敌人
(以某点(x1,y1,z1)为圆心范围1~5米生成5个敌人)
for (int i = 0; i < 5; i++)
{
float a = Random.Range(1, 5);
//从原点坐标获取任意一个方向的向量
Vector2 b = Random.insideUnitCircle;
//获取向量的单位向量
Vector2 c = b.normalized;
//得到位置
Vector3 d = new Vector3(x1 + c.x * a, y1, z1 + c.y * a);
Instantiate(enemy, d, transform.rotation);
}
(2)、敌人走向玩家
距离问题:
利用Vector.Distance(敌人位置,玩家位置);判断距离从而进行播放动画朝玩家靠近。
if (Vector3.Distance(transform.position, player.transform.position) <= 10)
方向问题:
//敌人指向玩家方向
dir = (player.transform.position - transform.position).normalized;
朝向问题:
transform.LookAt(player.transform.position);
(3)、判断敌人位置
a、点乘
//点乘
float a = Vector3.Dot(transform.forward, enemy.transform.position - player.transform.position);
if (a <= 0)
{
tipWarn.text = "警告:后方发现敌人";
}
else
{
tipWarn.text = "警告:前方发现敌人";
}
b、叉乘