45fan.com - 路饭网

搜索: 您的位置主页 > 网络频道 > 阅读资讯:双人坦克大战 - Unity3D

双人坦克大战 - Unity3D

2019-04-10 08:46:18 来源:www.45fan.com 【

一个简单的双人坦克游戏(3D)。

双人坦克大战 - Unity3D

GitHub
https://github.com/SSGamble/TanksGame

总结

  • 双人操作
    • 拆分 Horizontal 和 Vertical 轴,为坦克设置编号,区分控制
  • 相机跟随两个物体
    • 让相机跟随两个物体的正中心
  • 添加音效
    • 利用声音组件,设置音效,控制播放。

创建场景

拖入场景模型

创建坦克

拖入坦克模型,并为坦克添加 Box Collider 组件,设置碰撞区域。

添加脚本控制坦克移动

因为是 3 维场景,坦克应在水平面移动,所以应该锁定刚体组件的 y 方向,和 x,z 的转向。即,只能在 xoz 平面移动,只能绕 y 轴旋转。

双人坦克大战 - Unity3D

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TankMovement : MonoBehaviour {

  private Rigidbody rigidbody;

  public float speed = 15; // 坦克的移动速度
  public float angularSpeed = 10; // 坦克的旋转速度

void Start () {
    rigidbody = this.GetComponent<Rigidbody>();
}

  // MonoBehaviour.FixedUpdate():在每个固定帧帧数被调用,在处理 Rigidbody 时,应该使用 FixedUpdate 而不是 Update
  private void FixedUpdate()
  {
    // 控制坦克前后移动
    float v = Input.GetAxis("Vertical");
    rigidbody.velocity = transform.forward * v * speed; // 修改刚体的速度,这种方式并不符合物理规律

    // 控制坦克左右旋转
    float h = Input.GetAxis("Horizontal");
    // angularVelocity 刚体角速度矢量,单位为弧度/秒。
    rigidbody.angularVelocity = transform.up * h * angularSpeed; // 绕 Y 轴旋转
  }
}

双人操作坦克

edit -> project settings -> input,拆分 Horizontal 和 Vertical 轴,为坦克设置编号,区分控制。

双人坦克大战 - Unity3D

坦克 ID

双人坦克大战 - Unity3D

拆分控制轴

public float tankID = 1; // 坦克的编号,用于控制两种不同的键盘操作
// 通过坦克编号区分控制
float v = Input.GetAxis("VerticalPlayer" + tankID); 
float h = Input.GetAxis("HorizontalPlayer" + tankID);

控制坦克发射子弹

拖入子弹模型,为子弹添加碰撞体和刚体,设为触发器,并将其设为预制体。

创建空物体,设置位置到坦克发射口,此为坦克的开火位置。

双人坦克大战 - Unity3D

坦克的开火位置

找到开火位置,实例化子弹,并为子弹设置速度,实现发射效果,为子弹添加触发检测,实现爆炸效果,最后要记得在适合的时候销毁子弹和爆炸效果。

控制坦克开火

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 坦克
///   控制坦克开火
/// </summary>
public class TankAttack : MonoBehaviour {

  private Transform firePosition; // 开火位置
  public GameObject shell; // 子弹,需要赋值
  public KeyCode fireKey = KeyCode.Space; // 开火按键
  public float shellSpeed = 15; // 子弹发射速度

// Use this for initialization
void Start () {
    // Transform.Find,public Transform Find(string name); 按名称查找子元素并返回它。
    firePosition = transform.Find("FirePosition"); // 查找开火位置
}

// Update is called once per frame
void Update () {
    if (Input.GetKeyDown(fireKey))
    {
      GameObject obj = GameObject.Instantiate(shell, firePosition.position, firePosition.rotation) as GameObject; // 实例化子弹
      obj.GetComponent<Rigidbody>().velocity = obj.transform.forward * shellSpeed;

    }
}
}

子弹的触发检测,产生爆炸效果

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 子弹
///   子弹的触发检测,产生爆炸效果
/// </summary>
public class Shell : MonoBehaviour {

  public GameObject shellExplosion; // 爆炸效果,需勾选爆炸效果的 Play On Awake,即生成就开始

  // 触发检测
  private void OnTriggerEnter(Collider collider)
  {
    GameObject.Instantiate(shellExplosion, transform.position, transform.rotation); // 实例化爆炸效果,位置就是当前子弹的位置
    GameObject.Destroy(this.gameObject); // 把自身销毁
  }
}

爆炸效果的销毁

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 爆炸效果
///   爆炸效果的销毁
/// </summary>
public class DestroyFotTime : MonoBehaviour {

  public float delayTime; // 爆炸效果延迟销毁时间

void Start () {
    Destroy(this.gameObject, delayTime); // 爆炸效果,延迟销毁
}
}

设置坦克生命值并控制死亡

当子弹碰到坦克时,发送一条信息,坦克收到消息,做出相应的处理。

在子弹的触发检测里设置

// 如果子弹碰撞到了 Tank,给 Tank 发送一条消息,Tank 里会创建一个 TankDamage 方法来处理消息
if (collider.tag == "Tank")
{
collider.SendMessage("TankDamage");
}

坦克生命处理

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 坦克,坦克的生命处理
/// </summary>
public class TankHealth : MonoBehaviour {

  public int hp = 100; // 坦克的生命值
  public GameObject tankExplosion; // 坦克死亡的爆炸效果

  /// <summary>
  /// 收到消息,坦克受到伤害
  /// </summary>
  void TankDamage()
  {
    if (hp <= 0) return;
    hp = hp - Random.Range(20, 30); // 随机减少生命值
    if (hp <= 0) // 收到伤害后,如果死亡
    {
      GameObject.Instantiate(tankExplosion, transform.position, transform.rotation); // 生成爆炸效果
      GameObject.Destroy(this.gameObject); // 销毁坦克
    }
  }
}

设置相机跟随

让相机跟随两个坦克的正中心。首先获得两个坦克的距离,让相机处在一个合适的位置,此时相机的视野距离应该和两个坦克的距离成一个倍数,比如:

视野 = 18,坦克1 = 0.44,坦克2 = 9.57,此时倍数应该是 2 左右。

让相机一直保持在这个距离即可。这样一来,两个坦克走近的时候,视野会变小,走远的时候,视野会变大。应设置一个最小视野,否则坦克距离很近的时候,视野会变得非常小,可能只看得见两个坦克了,这是很不科学的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 相机:让相机跟随两个坦克的正中心
/// </summary>
public class Follow : MonoBehaviour {

  public Transform player1; // 坦克 1
  public Transform player2; //坦克 2

  private Camera mainCamera; // 主相机
  private Vector3 offect; // 偏移,相机和两个坦克正中心

  private float size;

  void Start () {
    offect = transform.position - (player1.position + player2.position) / 2; // 两个坦克的正中心
    mainCamera = this.GetComponent<Camera>(); // 获取相机
    mainCamera.orthographic = true; // 将相机设置为正交法

  }

  void Update () {
    if (player1 == null || player2 == null) return; // 如果任何一个坦克消失,游戏结束,取消相机跟随
transform.position = offect + (player1.position + player2.position) / 2; // 两个坦克的中心位置
    float distance = Vector3.Distance(player1.position, player2.position); // 两个坦克的距离
    if (distance < 9) // 即使两个坦克的距离很近,相机的最小视野也应是一个最佳倍数
      size = 9f; // 相机视野的距离 = 初始倍数
    else // 两个坦克距离很远
      size = distance * 1; // 相机视野的距离 = 两个坦克的距离 * 一个合适的倍数
    mainCamera.orthographicSize = size; // 设置相机视野
  }
}

添加音效

BGM

双人坦克大战 - Unity3D

音效

private AudioSource audioSource; // 声音组件
public AudioClip idleAudio; // 坦克空闲时的音效
public AudioClip drivingAudio; // 坦克移动时的音效

// 获取 AudioSource 的组件
audioSource = this.GetComponent<AudioSource>(); 

// 在适合的时候播放音效
if (Mathf.Abs(h) > 0.1 || Mathf.Abs(v) > 0.1) // 坦克移动时
{
  audioSource.clip = drivingAudio; // 设置音效
  if (audioSource.isPlaying == false) // 如果没有播放,播放
    audioSource.Play();
}
else // 坦克空闲时
{
  audioSource.clip = idleAudio;
  if (audioSource.isPlaying == false)
    audioSource.Play();
}

增加血条 - 游戏结束

添加 UI Slider,设置背景和填充图片,设置 Image TypeFilled

public Slider hpSlider; // 血条
private int hpTotal; // 血量


private void Start(){
  hpTotal = hp;
}

// 坦克受到伤害时
hpSlider.value = 1 - ((float)hp / hpTotal); // 设置 Slider 血条 的值
 
 

本文地址:http://www.45fan.com/a/question/100337.html
Tags: 大战 坦克 双人
编辑:路饭网
  • 上一篇:确保 Web 安全的 HTTPS
  • 下一篇:没有了
  • 关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部