Unity3D--项目:CS局域网之战(二)

Unity3D--项目:CS局域网之战(二)_第1张图片
Image.png
1、角色控制

我们的资源里面已经包含第一人称与第三人称控制器,可以学习一番。
第一人称:

Unity3D--项目:CS局域网之战(二)_第2张图片
Paste_Image.png

第三人称:


Unity3D--项目:CS局域网之战(二)_第3张图片
Paste_Image.png
1-1、我们通过第一人称视野来进行角色控制
Unity3D--项目:CS局域网之战(二)_第4张图片
Paste_Image.png

最终效果:


111.gif
1-2、控制角色摄像机跟随

将摄像机移动至角色头部附近


Unity3D--项目:CS局域网之战(二)_第5张图片
Paste_Image.png

给摄像机添加脚本控制:


Unity3D--项目:CS局域网之战(二)_第6张图片
Paste_Image.png
Unity3D--项目:CS局域网之战(二)_第7张图片
Paste_Image.png

实际代码模块:


Unity3D--项目:CS局域网之战(二)_第8张图片
Paste_Image.png
1-3摄像机跟随方式二

我们除了扔进头部中,还可以扔进骨骼头部,保持相对位置,然后通过弯腰等骨骼动画来达到相机跟随

Unity3D--项目:CS局域网之战(二)_第9张图片
Paste_Image.png

那就添加脚本,修改相应的值
transform.localEulerAngles:自身欧拉角,说这是对象自己相对于父对象的旋转角度,该变量可用于读取和设置该角度。不可以用于递增,角度超过360度将会失效。

Unity3D--项目:CS局域网之战(二)_第10张图片
Paste_Image.png

修改成Y轴操纵


Unity3D--项目:CS局域网之战(二)_第11张图片
Paste_Image.png
注意:

1、假如产生动画后,上下视野执行不了,那么我们可以将这一套Update()更新的代码置入LateUpdate()中
原因:这是因为每一次动画执行也是在Update执行,会覆盖我们的操作,所以要在Update之后的函数中执行
2、如果发现摄像机的视野偏差太严重,可以放置在骨骼父级里面。当时一定要在有控制视野脚本的骨骼下面。

1-4、角色动画控制

将动画扔进去


Unity3D--项目:CS局域网之战(二)_第12张图片
Paste_Image.png
Unity3D--项目:CS局域网之战(二)_第13张图片
Paste_Image.png
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、武器挂载

位置调整好,运行后查看具体效果


Unity3D--项目:CS局域网之战(二)_第14张图片
Paste_Image.png
1-7、制作子弹

子弹由于只需要从第一人称的视角看到,所以2D面片就可以解决这个问题

Unity3D--项目:CS局域网之战(二)_第15张图片
Paste_Image.png

做好保存为预制物。

1-8、子弹移动脚本

让子弹具有移动功能,首先看一张子弹运行图


Unity3D--项目:CS局域网之战(二)_第16张图片
Paste_Image.png
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)
        {  // 如果检测到什么物体,应该做什么动作
           // 具体里面,在制作完相应的特效后,再写。
        } 
    }
}
Unity3D--项目:CS局域网之战(二)_第17张图片
Paste_Image.png
1-10、枪口特效

设置Quad将材质拖进去就可以


Unity3D--项目:CS局域网之战(二)_第18张图片
Paste_Image.png

因为我们的特效是跟随枪口的,伴随着子弹的射击产生的,所以扔进我们的枪中,重置坐标系,移动到合适位置。


Unity3D--项目:CS局域网之战(二)_第19张图片
Paste_Image.png

通过脚本来控制:枪口效果

Unity3D--项目:CS局域网之战(二)_第20张图片
Paste_Image.png

脚本:

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、枪的射击(不同于上面的子弹飞行脚本)

查看弹痕素材:


Unity3D--项目:CS局域网之战(二)_第21张图片
Paste_Image.png

如何将两张图片显示一个材质球上面呢?选中材质,更换Shader

Unity3D--项目:CS局域网之战(二)_第22张图片
Paste_Image.png

将拥有法线贴图的材质球设置到我们的弹痕对象中


Unity3D--项目:CS局域网之战(二)_第23张图片
Paste_Image.png
Unity3D--项目:CS局域网之战(二)_第24张图片

因为不需要碰撞检测,删除Mesh Collider,只需要修改里面材质的ManText属性的颜色通道


Unity3D--项目:CS局域网之战(二)_第25张图片
Paste_Image.png

如何拿到里面的材质的MainText透明通道呢?

Unity3D--项目:CS局域网之战(二)_第26张图片
Paste_Image.png
Unity3D--项目:CS局域网之战(二)_第27张图片
Paste_Image.png
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、鼠标按键射击

首先要在我们的枪口创建一个空物体,调整位置用来挂载我们的射击脚本,实例化子弹

Unity3D--项目:CS局域网之战(二)_第28张图片
Paste_Image.png
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、将制作好的弹痕添加到被射击的物体上面

打开上面我们做好子弹预制物挂载的脚本(让子弹飞脚本)

Unity3D--项目:CS局域网之战(二)_第29张图片
Paste_Image.png

修改脚本中的碰撞内容:
Hit.nomal // 可以得到碰撞点的垂线向量;


Unity3D--项目:CS局域网之战(二)_第30张图片
Paste_Image.png
   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);//移动子弹的位置

你可能感兴趣的:(Unity3D--项目:CS局域网之战(二))