unity 项目仿cs知识点

一、简介
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、叉乘
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44706943/article/details/127181588
今日推荐