本项目使用了复杂的动画系统,实现了各种空间移动动作、使用不同枪支打僵尸、以及僵尸的追杀和死亡动画。
b站动画:Unity休闲射击打僵尸_哔哩哔哩_bilibili
1.代码实现
本项目的主要侧重点在动画,因此代码部分较为简单,以下是三个脚本的简介
①Player.cs
这段代码主要实现了玩家角色的功能,包括前后左右移动、冲刺、跳跃等控制方法,布置了三种枪械:ak47、狙击枪、散弹枪,以及切换枪械及使用狙击镜和射击的方式,以及为狙击镜和普通视角各设置了一个相机。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Player : MonoBehaviour
{ public GameObject ak47;
public GameObject sniper1;
public GameObject shortgun1;
GameObject current;
public float walkingspeed;
public float runningspeed;
Animator animator;
public float mouseSensitivity = 100.0f;
public Camera maincamera;
public Camera scopecamera;
public GameObject scopeoverlay;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
current = ak47;
// 隐藏光标
Cursor.visible = false;
// 锁定光标到游戏窗口中心
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
// 按下 Esc 键解锁光标
if (Input.GetKeyDown(KeyCode.Escape))
{
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
if (Input.GetKeyDown(KeyCode.Alpha1))
{
current.SetActive(false);
Debug.Log("alpha1");
ak47.SetActive(true);
current = ak47;
}
if (Input.GetKeyDown(KeyCode.Alpha2))
{
current.SetActive(false);
Debug.Log("alpha2");
shortgun1.SetActive(true);
current = shortgun1;
}
if (Input.GetKeyDown(KeyCode.Alpha3))
{
current.SetActive(false);
Debug.Log("alpha3");
sniper1.SetActive(true);
current = sniper1;
}
Rigidbody rb = GetComponent<Rigidbody>();
//控制旋转
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
mouseY = Mathf.Clamp(mouseY, -90f, 90f);
transform.Rotate(Vector3.up * mouseX);
if(scopeoverlay.activeSelf)
{
scopecamera.transform.Rotate(Vector3.left * mouseY);
}
else
{
maincamera.transform.Rotate(Vector3.left * mouseY);
}
float H = Input.GetAxis("Horizontal");
float V = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(H, 0.0f, V);
if (animator.GetBool("running"))
{
movement = maincamera.transform.rotation * movement * runningspeed;
}
else
{
movement = maincamera.transform.rotation * movement * walkingspeed;
}
rb.velocity = new Vector3(movement.x, rb.velocity.y, movement.z);
//控制水平移动
if (Input.GetKey(KeyCode.W))
{
animator.SetBool("walking",true);
if(Input.GetKey(KeyCode.LeftShift))
{
animator.SetBool("running", true);
}
else
{
animator.SetBool("running", false);
}
}
else
{
animator.SetBool("walking", false);
animator.SetBool("running", false);
}
//向后运动
if (Input.GetKey(KeyCode.S))
{
animator.SetBool("backwalk", true);
Debug.Log("backwalking");
}
else
{
animator.SetBool("backwalk", false);
}
//向左运动
if (Input.GetKey(KeyCode.A))
{
animator.SetBool("leftwalk", true);
}
else
{
animator.SetBool("leftwalk", false);
}
//向右运动
if(Input.GetKey(KeyCode.D))
{
animator.SetBool("rightwalk", true);
}
else
{
animator.SetBool("rightwalk", false);
}
//控制跳跃
if(Input.GetKeyDown(KeyCode.Space))
{
if(animator.GetBool("Canjump")==false)
{
return;
}
animator.SetTrigger("jump");
rb.velocity = new Vector3(rb.velocity.x, rb.velocity.y + 5, rb.velocity.z);
animator.SetBool("Canjump", false);
}
if(Input.GetKeyDown(KeyCode.R))
{
Debug.Log(transform.rotation);
transform.Rotate(new Vector3(0, 90, 0));
Debug.Log(transform.rotation);
}
}
// 当玩家碰撞到其他物体时调用
void OnCollisionEnter(Collision collision)
{
// 检查碰撞的游戏对象是否有 "Terrain" 标签
if (collision.gameObject.CompareTag("Terrain"))
{
animator.SetBool("Canjump", true);
Debug.Log("落地了");
}
}
}
②Zombie.cs
该文件实现了僵尸攻击玩家的动作,被射击时扣血,以及死亡的动作
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Zombie : MonoBehaviour
{
public Transform player;
Animator anim;
public float HP;
// Start is called before the first frame update
void Start()
{
anim = GetComponent<Animator>();
anim.SetBool("killed", false);
}
// Update is called once per frame
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.CompareTag("AKbullet"))
{
HP -= 30;
}
else if(collision.gameObject.CompareTag("Sniperbullet"))
{
HP -= 100;
}
else if(collision.gameObject.CompareTag("shortgunbullet"))
{
HP -= 15;
}
}
void Update()
{
// 朝向玩家
Vector3 directionToPlayer = player.position - transform.position;
directionToPlayer.y = 0; // 确保僵尸不会向上或向下倾斜
Quaternion rotationToPlayer = Quaternion.LookRotation(directionToPlayer);
transform.rotation = rotationToPlayer;
Rigidbody rb = GetComponent<Rigidbody>();
if(HP <= 0)
{
anim.SetBool("killed", true);
anim.applyRootMotion = false;
rb.isKinematic = true;
}
if ((this.transform.position - player.transform.position).magnitude < 1.5f)
{
anim.SetBool("attack", true);
anim.SetBool("running",false);
}
else
{
anim.SetBool("attack", false);
anim.SetBool("running", true);
}
}
}
③ZombieGenerator.cs
这个文件定义了一个僵尸生成器模块,可以在地图的指定位置生成僵尸
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ZombieGenerator : MonoBehaviour
{
public List<Transform> locations;
public Transform player;
public GameObject zombie_prefab;
// Start is called before the first frame update
void Start()
{
foreach(Transform t in locations)
{
GameObject zb = Instantiate(zombie_prefab);
zb.transform.position = t.position;
zb.GetComponent<Zombie>().player = player;
}
}
// Update is called once per frame
void Update()
{
}
}
2.动画实现
本项目的亮点在于细腻的动画设计,包括玩家的空间移动、冲刺、跳跃以及这些移动对应的不同持枪动作;对于僵尸,也有包括追赶、攻击和死亡的动画控制。
①Mycontroller.controller
该控制器实现了对玩家角色的动画控制,会在玩家按下按键时切换到对应的动作,同时持枪的姿势也会有细微的变化
②zombiecontroller.controller
僵尸控制器用于控制僵尸做出攻击玩家、追击、死亡的动作
谢谢观看!