1、角色控制
我们的资源里面已经包含第一人称与第三人称控制器,可以学习一番。
第一人称:
第三人称:
1-1、我们通过第一人称视野来进行角色控制
最终效果:
1-2、控制角色摄像机跟随
将摄像机移动至角色头部附近
给摄像机添加脚本控制:
实际代码模块:
1-3摄像机跟随方式二
我们除了扔进头部中,还可以扔进骨骼头部,保持相对位置,然后通过弯腰等骨骼动画来达到相机跟随
那就添加脚本,修改相应的值
transform.localEulerAngles:自身欧拉角,说这是对象自己相对于父对象的旋转角度,该变量可用于读取和设置该角度。不可以用于递增,角度超过360度将会失效。
修改成Y轴操纵
注意:
1、假如产生动画后,上下视野执行不了,那么我们可以将这一套Update()更新的代码置入LateUpdate()中
原因:这是因为每一次动画执行也是在Update执行,会覆盖我们的操作,所以要在Update之后的函数中执行
2、如果发现摄像机的视野偏差太严重,可以放置在骨骼父级里面。当时一定要在有控制视野脚本的骨骼下面。
1-4、角色动画控制
将动画扔进去
using UnityEngine;
using System.Collections;
public class PlayerAnimation : MonoBehaviour
{
private Animation ani;
private CharacterController charactor;
void Start()
{
ani = GetComponent();
charactor = GetComponent();
}
void Update()
{
if (charactor.isGrounded == true)
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
if (Mathf.Abs(h) > 0.2 || Mathf.Abs(v) > 0.2)
{
ani["soldierWalk"].speed = 2.0f;
PlayAni("soldierWalk");
}
else
{
PlayAni("soldierIdle");
}
}
else
{
PlayAni("soldierFalling");
}
}
// 传入名字播放动画
void PlayAni(string aniName)
{
// 控制动画播放速度
//ani[aniName].speed = 1.0f;
ani.CrossFade(aniName, 1.0f);
}
1-5、关于动画的延伸
ani.Play ();播放默认动画。
ani.Play ("animation"); 将开始播放名称为animation的动画
ani.PlayQueued ("animation"); 排队播放名称为animation的动画
ani.Play ("animation", PlayMode.StopAll); 播放animation动画停止其他动画。
ani.CrossFade ("animation",1.5f);在一定时间内淡入名称为animation的动画并且淡出其他动画
ani.Stop ();停止所有动画。
ani.wrapMode = WrapMode.Loop;使用动画循环模式
WrapMode.Default:从动画剪辑中读取循环模式(默认是Once)。
WrapMode.Once:当时间播放到末尾的时候停止动画的播放。
WrapMode.Loop:当时间播放到末尾的时候重新播放从开始播放。
WrapMode.ClampForever:播放动画。当播放到结尾的时候,动画总是处于最后一帧的采样状态。
1-6、武器挂载
位置调整好,运行后查看具体效果
1-7、制作子弹
子弹由于只需要从第一人称的视角看到,所以2D面片就可以解决这个问题
做好保存为预制物。
1-8、子弹移动脚本
让子弹具有移动功能,首先看一张子弹运行图
using UnityEngine;
using System.Collections;
// 子弹预制物脚本:让子弹具有移动功能
public class Bullet : MonoBehaviour {
//子弹初始速度,开发阶段可以让其变小一些
private float speed = 30;
public GameObject[] bulletoles; //
void Start () {
// 3秒后摧毁子弹,不然我们的子弹会一直消耗我们的内存
Destroy(this.gameObject, 3f);
}
void Update () {
Vector3 currentPos = transform.position;
transform.Translate(transform.forward * speed * Time.deltaTime);
// 差值
Vector3 distance = transform.position - currentPos;
// 子弹上一帧与这一帧的距离
float length = (transform.position - currentPos).magnitude;
RaycastHit hit;
// 第一个参数是开始点,第二个参数是方向,hit,最后一个是摄像-长度
bool isCollider = Physics.Raycast(currentPos, distance, out hit, length);
if (isCollider)
{ // 如果检测到什么物体,应该做什么动作
// 具体里面,在制作完相应的特效后,再写。
}
}
}
1-10、枪口特效
设置Quad将材质拖进去就可以
因为我们的特效是跟随枪口的,伴随着子弹的射击产生的,所以扔进我们的枪中,重置坐标系,移动到合适位置。
通过脚本来控制:枪口效果
脚本:
using UnityEngine;
using System.Collections;
// 开枪后的枪口特效脚本:主要看到枪口的火花效果
public class PlayGunFlash : MonoBehaviour {
// 特效数组 - 保存所有枪口特效
public Material[] falshMaterials;
// 获取渲染组件
private Renderer render;
// 当前的特效索引
public int index;
void Start()
{
render = GetComponent();
// render.enabled = false;
}
void Update()
{
if (Input.GetMouseButtonDown(0))
{
render.enabled = true;
PlayFalsh();
}
else
{
render.enabled = false;
}
}
// 播放动画
public void PlayFalsh()
{
index++; // 每一次调用函数,索引增加
index %= 4; // 控制索引在[0-3]之间
render.enabled = true; // 执行这个函数表示枪口特效要渲染出来
render.material = falshMaterials[index];// 设置渲染器的渲染材质
}
}
至此我们的游戏角色基本搞定,将角色保存为预制物。
2、枪的射击(不同于上面的子弹飞行脚本)
查看弹痕素材:
如何将两张图片显示一个材质球上面呢?选中材质,更换Shader
将拥有法线贴图的材质球设置到我们的弹痕对象中
因为不需要碰撞检测,删除Mesh Collider,只需要修改里面材质的ManText属性的颜色通道
如何拿到里面的材质的MainText透明通道呢?
public class BulletHoleRender : MonoBehaviour {
private Renderer render; // 拿到弹痕渲染器
private float speed = 1f; // 设置渐变时间
private float time = 0; // 弹痕消失时间
void Start()
{
render = GetComponent();
}
// Update is called once per frame
void Update()
{
time += Time.deltaTime;
if (time > 2)
{ // 颜色渐变
render.material.color = Color.Lerp(render.material.color, Color.clear, speed * Time.deltaTime);
}
if (time > 5)
{ // 时间大于5秒,摧毁这个游戏对象
Destroy(this.gameObject);
}
}
}
2-1、鼠标按键射击
首先要在我们的枪口创建一个空物体,调整位置用来挂载我们的射击脚本,实例化子弹
using UnityEngine;
using System.Collections;
// 开火脚本,按键射击
public class ShootBullet : MonoBehaviour {
private bool isFire = false; // 是否开火
private float timer = 0; // 计时器
public int shootRate = 10; // 每秒射击多少子弹
public PlayGunFlash playFlash; // 播放枪口特效
public GameObject bullet; // 子弹预制物
void Update () {
if (Input.GetMouseButtonDown(0))
{
isFriing = true;
}
if (Input.GetMouseButtonUp(0))
{
isFriing = false;
}
if (isFriing)
{
timer += Time.deltaTime;
if (timer > 1f / shootRate)
{
Shoot();
timer = 0;
}
}
}
void Shoot()
{
playFlash.PlayFalsh();
// 实例化子弹对象到当前的物体
GameObject.Instantiate(bulletPrefab, transform.position, transform.rotation);
}
}
2-2、将制作好的弹痕添加到被射击的物体上面
打开上面我们做好子弹预制物挂载的脚本(让子弹飞脚本)
修改脚本中的碰撞内容:
Hit.nomal // 可以得到碰撞点的垂线向量;
int index = Random.Range(0, 2);
GameObject bulletHolePrefab = bulletHoles[index];
Vector3 po = hit.point; //拿到碰撞位置
// 实例化弹痕
GameObject go = GameObject.Instantiate(bulletHolePrefab, po, Quaternion.identity) as GameObject;
go.transform.LookAt(hit.point - hit.normal); //如果出不来,可以修改符号
go.transform.Translate(Vector3.back * 0.01f);//移动子弹的位置
、