赞
踩
人机交互Input 中实现了通过键盘控制坦克运动,通过鼠标控制坦克发射炮弹,本文将在此基础上,增加血条(HP)功能。炮弹命中后,HP 值会减少,因此需要应用到 刚体组件Rigidbody 和 碰撞体组件Collider;从不同角度攻击敌人时,敌人的血条始终朝向相机,因此需要用到 相机跟随;血条通过 Image 显示,因此需要用到 UGUI之Image;玩家的血条始终显示在屏幕左上角,因此需要使用到 锚点。
1)需求实现
2)涉及技术栈
本文代码资源见 → Unity3D 血条效果。
2 游戏对象
1)游戏界面
2)游戏对象层级结构
3)Transform组件参数
1. 玩家 Transform 组件参数
Name | Type | Position | Rotation | Scale | Color/Texture |
Player | Empty | (0, 0.25, -5) | (0, 0, 0) | (1, 1, 1) | #228439FF |
Botton | Cube | (0, 0, 0) | (0, 0, 0) | (2, 0.5, 2) | #228439FF |
Top | Cube | (0, 0.5, 0) | (0, 0, 0) | (1, 0.5, 1) | #228439FF |
Gun | Cylinder | (0, 0, 1.5) | (90, 0, 0) | (0.2, 1, 0.4) | #228439FF |
FirePoint | Empty | (0, 1.15, 0) | (0, 0, 0) | (1, 1, 1) | —— |
补充:Player 游戏对象添加了刚体组件,并修改 Mass = 100,Drag = 1,AngularDrag = 0.1,Freeze Rotation 中勾选 X 和 Z。
2. 玩家 HP RectTransform 组件参数
Name | Type | Rect | Width/Height | Pos | Color/Texture |
PlayerHP | Canvas | —— | —— | —— | —— |
Panel | Panel | (0, 0, 0, 0) | —— | (-, -, 0) | #FFFFFF00 |
HealthBG | Image | (0, 0.25, -5) | (200, 20) | (125, -30, 0) | #FFFFFFFF |
Health | Image | (0, 0.25, -5) | (200, 20) | (125, -30, 0) | #FF2230FF |
补充: 玩家 PlayerHP 的 Canvas 渲染模式是 Screen Space - Overlay,Health 的 ImageType 设置为 Filled,Fill Method 设置为 Horizontal。
3. 敌人 Transform 组件参数
Name | Type | Position | Rotation | Scale | Color/Texture |
Enemy | Empty | (0, 0.25, 5) | (0, 180, 0) | (1, 1, 1) | #15D3F9FF |
Botton | Cube | (0, 0, 0) | (0, 0, 0) | (2, 0.5, 2) | #15D3F9FF |
Top | Cube | (0, 0.5, 0) | (0, 0, 0) | (1, 0.5, 1) | #15D3F9FF |
Gun | Cylinder | (0, 0, 1.5) | (90, 0, 0) | (0.2, 1, 0.4) | #15D3F9FF |
FirePoint | Empty | (0, 1.15, 0) | (0, 0, 0) | (1, 1, 1) | —— |
补充:Enemy 游戏对象添加了刚体组件,并修改 Mass = 100,Drag = 0.5,AngularDrag = 0.1,Freeze Rotation 中勾选 X 和 Z。
4. 敌人 HP RectTransform 组件参数
Name | Type | Width/Height | Pos | Color/Texture |
HP | Canvas | (2, 0.2) | (0, 0.85, 0) | —— |
HealthBG | Image | (2, 0.2) | (0, 0, 0) | #FFFFFFFF |
Health | Image | (2, 0.2) | (0, 0, 0) | #FF2230FF |
补充: 敌人 HP 的 Canvas 渲染模式是 World Space,Health 的 ImageType 设置为 Filled,Fill Method 设置为 Horizontal。
5. 地面和炮弹 Transform 组件参数
Name | Type | Position | Rotation | Scale | Color/Texture |
Plane | Plane | (0, 0, 0) | (0, 0, 0) | (10, 10, 10) | GrassRockyAlbedo |
Bullet | Sphere | (0, 0.5, -5) | (0, 0, 0) | (0.3, 0.3, 0.3) | #228439FF |
补充:炮弹作为预设体拖拽到 Assets/Resources/Prefabs 目录下,并且添加了刚体组件。
1)CameraController
CameraController.cs
- using UnityEngine;
-
- public class CameraController : MonoBehaviour {
- private Transform player; // 玩家
- private Vector3 relaPlayerPos; // 相机在玩家坐标系中的位置
- private float targetDistance = 15f; // 相机看向玩家前方的位置
-
- private void Start() {
- relaPlayerPos = new Vector3(0, 4, -8);
- player = GameObject.Find("Player/Top").transform;
- }
-
- private void LateUpdate() {
- CompCameraPos();
- }
-
- private void CompCameraPos() { // 计算相机坐标
- Vector3 target = player.position + player.forward * targetDistance;
- transform.position = transformVecter(relaPlayerPos, player.position, player.right, player.up, player.forward);
- transform.rotation = Quaternion.LookRotation(target - transform.position);
- }
-
- // 求以origin为原点, locX, locY, locZ 为坐标轴的本地坐标系中的向量 vec 在世界坐标系中对应的向量
- private Vector3 transformVecter(Vector3 vec, Vector3 origin, Vector3 locX, Vector3 locY, Vector3 locZ) {
- return vec.x * locX + vec.y * locY + vec.z * locZ + origin;
- }
- }
说明: CameraController 脚本组件挂在 MainCamera 游戏对象上。
2)PlayerController
PlayerController.cs
- using System;
- using UnityEngine;
-
- public class PlayerController : MonoBehaviour {
- private Transform firePoint; // 开火点
- private GameObject bulletPrefab; // 炮弹预设体
- private float tankMoveSpeed = 4f; // 坦克移动速度
- private float tankRotateSpeed = 2f; // 坦克转向速度
- private float fireWaitTime = float.MaxValue; // 距离上次开火已等待的时间
- private float bulletCoolTime = 0.15f; // 炮弹冷却时间
-
- private void Start() {
- firePoint = transform.Find("Top/Gun/FirePoint");
- bulletPrefab = (GameObject) Resources.Load("Prefabs/Bullet");
- }
-
- private void Update() {
- fireWaitTime += Time.deltaTime;
- float hor = Input.GetAxis("Horizontal");
- float ver = Input.GetAxis("Vertical");
- Move(hor, ver);
- if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space)) {
- Fire();
- }
- }
-
- private void Move(float hor, float ver) { // 坦克移动
- if (Math.Abs(hor) > 0.1f || Math.Abs(ver) > 0.1f) {
- GetComponent<Rigidbody>().velocity = transform.forward * tankMoveSpeed * ver;
- GetComponent<Rigidbody>().angularVelocity = Vector3.up * tankRotateSpeed * hor;
- }
- }
-
- private void Fire() { // 开炮
- if (fireWaitTime > bulletCoolTime) {
- BulletInfo bulletInfo = new BulletInfo("PlayerBullet", Color.red, transform.forward, 10f, 15f);
- GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity);
- bullet.AddComponent<BulletController>().SetBulletInfo(bulletInfo);
- fireWaitTime = 0f;
- }
- }
- }
说明: PlayerController 脚本组件挂在 Player 游戏对象上。
3)EnemyController
EnemyController.cs
- using UnityEngine;
- using UnityEngine.UI;
-
- public class EnemyController : MonoBehaviour {
- private Transform target; // 目标
- private Transform top; // 炮头
- private Transform firePoint; // 开火点
- private Transform hp; // 血条
- private GameObject bulletPrefab; // 炮弹预设体
- private float rotateSpeed = 0.4f; // 坦克转向速度
- private float fireWaitTime = float.MaxValue; // 距离上次开火已等待的时间
- private float bulletCoolTime = 1f; // 炮弹冷却时间
-
- private void Start () {
- target = GameObject.Find("Player/Top").transform;
- top = transform.Find("Top");
- firePoint = transform.Find("Top/Gun/FirePoint");
- hp = transform.Find("HP");
- bulletPrefab = (GameObject) Resources.Load("Prefabs/Bullet");
- }
-
- private void Update () {
- fireWaitTime += Time.deltaTime;
- LookAtTarget();
- float angle = Vector3.Angle(target.position - top.position, top.forward);
- if (LookAtTarget()) {
- Fire();
- }
- HPLookAtCamera();
- }
-
- private bool LookAtTarget() {
- Vector3 dir = target.position - top.position;
- float angle = Vector3.Angle(dir, top.forward);
- if (angle > 5) {
- int axis = Vector3.Dot(Vector3.Cross(dir, top.forward), Vector3.up) > 0 ? -1 : 1;
- GetComponent<Rigidbody>().angularVelocity = axis * Vector3.up * rotateSpeed;
- return false;
- }
- GetComponent<Rigidbody>().angularVelocity = Vector3.zero;
- return true;
- }
-
- private void HPLookAtCamera() {
- Vector3 cameraPos = Camera.main.transform.position;
- Vector3 target = new Vector3(cameraPos.x, hp.position.y, cameraPos.z);
- hp.LookAt(target);
- }
-
- private void Fire() {
- if (fireWaitTime > bulletCoolTime) {
- BulletInfo bulletInfo = new BulletInfo("EnemyBullet", Color.yellow, top.forward, 5f, 10f);
- GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity); // 通过预设体创建炮弹
- bullet.AddComponent<BulletController>().SetBulletInfo(bulletInfo);
- fireWaitTime = 0;
- }
- }
- }
说明: EnemyController 脚本组件挂在 Enemy 游戏对象上。
4)BulletController
BulletController.cs
- using UnityEngine;
- using UnityEngine.UI;
-
- public class BulletController : MonoBehaviour {
- private BulletInfo bulletInfo; // 炮弹信息
- private volatile bool isDying = false;
-
- private void Start () {
- gameObject.name = bulletInfo.name;
- GetComponent<MeshRenderer>().material.color = bulletInfo.color;
- float lifeTime = bulletInfo.fireRange / bulletInfo.speed; // 存活时间
- Destroy(gameObject, lifeTime);
- }
-
- private void Update () {
- transform.GetComponent<Rigidbody>().velocity = bulletInfo.flyDir * bulletInfo.speed;
- }
-
- private void OnCollisionEnter(Collision other) {
- if (isDying) {
- return;
- }
- if (IsHitEnemy(gameObject.name, other.gameObject.name)) {
- other.transform.Find("HP/Health").GetComponent<Image>().fillAmount -= 0.1f;
- isDying = true;
- Destroy(gameObject, 0.1f);
- } else if (IsHitPlayer(gameObject.name, other.gameObject.name)) {
- GameObject.Find("PlayerHP/Panel/Health").GetComponent<Image>().fillAmount -= 0.1f;
- isDying = true;
- Destroy(gameObject, 0.1f);
- }
- }
-
- public void SetBulletInfo(BulletInfo bulletInfo) {
- this.bulletInfo = bulletInfo;
- }
-
- private bool IsHitEnemy(string name, string otherName) { // 射击到敌军
- return name.Equals("PlayerBullet") && otherName.Equals("Enemy");
- }
-
- private bool IsHitPlayer(string name, string otherName) { // 射击到玩家
- return name.Equals("EnemyBullet") && otherName.Equals("Player");
- }
- }
说明: BulletController 脚本组件挂在 Bullet 游戏对象上(代码里动态添加)。
5)BulletInfo
BulletInfo.cs
- using UnityEngine;
-
- public class BulletInfo {
- public string name; // 炮弹名
- public Color color; // 炮弹颜色
- public Vector3 flyDir; // 炮弹飞出方向
- public float speed; // 炮弹飞行速度
- public float fireRange; // 炮弹射程
-
- public BulletInfo(string name, Color color, Vector3 flyDir, float speed, float fireRange) {
- this.name = name;
- this.color = color;
- this.flyDir = flyDir;
- this.speed = speed;
- this.fireRange = fireRange;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。