Unity百游修炼(3)——Tank_Battle(双人对战)具体制作全流程

[复制链接]
发表于 2025-10-25 07:45:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
一.项目简介

        《Tank_Battle》是一款基于 Unity 引擎开发的 3D 双人对战坦克游戏。玩家在游戏中操控各自的坦克,通过机动移动、旋转和发射子弹等利用,睁开剧烈的对战,旨在摧毁对方坦克以得到胜利。该项目团结了丰富的游戏元素和交互机制,为玩家带来沉醉式的游戏体验。
游戏画面如下:
   Tank_battle



二.创建场景

1.创建3D工程(定名为Tank_Battle)


2.导入unity_package(资源包)到Project窗口中(资源在素材内里)



3.将文件夹Prefab中levelart(场景)拖入到hierarchy窗口中


4.删除场景自带的直射光,由于levelart中自带了直射光


5.调治场景光线:Window——Reddering——Lighting——Environment(source光源调成color颜色,颜色调成和环境贴合的颜色)



6.Main camera改变天空场景颜色





三.添加坦克(加拖尾殊效)

1.把models中Tank拖放到Hierarchy视图中


2.把prefab中的DustTrall拖入到Tank上,复制一个,选中两个拖尾,分别将两个拖尾移动到轮子履带处


3.拖尾位置如下


4.给tank添加Box collider组件


5.调治collider的巨细


6.把tank酿成prefab,直接把tank拖到Projectors——Prefab文件夹中(为了反面坦克多了同一管理)





四.控制坦克前后移动

1.创建控制坦克移动的脚本并定名为Tank_ Move(记得创建一个Scripst文件夹同一管理脚本)


2.选择Tank,添加刚体组件Rigidbody


3.进入Tank_Move脚本

4.获取Tank自己Rigidbody组件

4.1创建刚体变量,生存
  1. public class TankMove : MonoBehaviour
  2. {
  3.     public Rigidbody Tank_body;//创建刚体变量接受Tank的刚体
  4.     // Start is called before the first frame update
  5.     void Start()
  6.     {
  7.         
  8.     }
  9.     // Update is called once per frame
  10.     void Update()
  11.     {
  12.         
  13.     }
  14. }
复制代码
4.2把脚本拖放到Tank身上,然后把Tank脚本的Tank_body变量指定为Tank自己的Rigidbody

5.按键控制tank前后移动

5.1按键ws控制移动
5.2检测按键ws按下并生存按下的返回值

 Input.GetAxisRaw();作用是:检测是否有按键按下,并返回float值
"Vertical"作用是:竖直方向
 
5.3按键使得坦克向前大概向后移动

transform.forward 的寄义
     方向表现:它是一个三维向量(Vector3 范例),指向游戏对象所面向的正火线。这个方向是相对于游戏对象的旋转而言的,当游戏对象的旋转发生改变时,transform.forward 的方向也会随之改变。


五.控制坦克旋转

1.按键ad控制旋转

2.检测按键ad按下并生存按下的返回值


3.绕Y轴移动


        这行代码的重要功能是设置坦克刚体(Tank_body)的角速率,从而让坦克绕着轴举行旋转。旋转的轴是游戏对象自身的向上方向(transform.up),即Y轴,旋转的速率由 r 和 TankRotate_Speed 共同决定。
4.完备代码显现




六.控制两辆坦克(实现双人一起玩)

1.打开Edit——Projectsettings——input Manger




2.包管ad只控制Player1的旋转,左右箭头只控制Player2的旋转

2.1光标放到Horizontal上,右击创建两个新的Horizontal,分别定名为Horizontal_Player1,Horizontal_Player2


2.2玩家一删除下图圈出来的内容,表现取消左右箭头控制进步

2.3玩家二删除下图圈出来的内容,表现取消ad按键控制旋转


3.包管ws只控制Player1的进步退却,上下箭头只控制Player2的进步退却

3.1光标放到Vertical上,右击创建两个新的Vertical,分别定名为Vertical_Player1,Vertical_Player2

3.2玩家一删除下图圈出来的内容,表现取消上下箭头控制进步

3.3玩家二删除下图圈出来的内容,表现取消ws按键控制旋转



七.控制坦克发射子弹

1.将子弹创建出来,并实例化

1.1将子弹素材拖入到Hierarchy中,并拖入Prefab成为预制体,并添加胶囊碰撞器



1.2修改碰撞体巨细(记得按下图利用,肯定要改成z轴)

1.3实例化子弹——确定位置。创建一个空物体,用来确定子弹发射位置,空物体是倾斜的(由于炮管是倾斜的),定名为fireposition



2.添加子弹攻击脚本Tank_Shoot——实例化子弹

2.1创建脚本

2.2创建变量担当位置,同时选中每次创建的子弹
  1. public Transform firePosition;//接受发射子弹的位置物体
  2. public GameObject ShellPrefab;//接受每次创建的实例化子弹
复制代码
2.3把脚本拖到发射位置物体上,然后把发射位置和发射的子弹预制体选中

2.4把发射位置物体,拖到Tank物体上,作为其子对象,如许就可以包管相对位置稳固了

2.5空格键控制子弹发射

2.6控制子弹飞行速率


八.子弹爆炸结果

1.创建子弹脚本Sheet

2.担当爆炸结果的预制体


3.当子弹触发器触碰到其他物体时,触发爆炸结果


4.我增长了一个开火也可以有爆炸结果,模仿后坐力很大





九.控制子弹造成伤害

1.给tank加tag标签,区分子弹是否触碰到了tank

2.写脚本——tank受到伤害处理惩罚的脚本
  1. public class Tank_health : MonoBehaviour
  2. {
  3.     public int hp = 100;//坦克血量
  4.     public GameObject Tankbaozha;//坦克爆炸效果
  5.     public AudioSource TankbaozhaAudioSource;
  6.     // Start is called before the first frame update
  7.     void Start()
  8.     {
  9.         
  10.     }
  11.     // Update is called once per frame
  12.     void Update()
  13.     {
  14.         
  15.     }
  16.     void HurtHealthy()
  17.     {
  18.         if (hp < 0)
  19.         {
  20.             return;
  21.         }
  22.         hp -= Random.Range(10, 20);//伤害是随机的 10  20
  23.         if (hp < 0)//坦克没了
  24.         {
  25.             TankbaozhaAudioSource.Play();
  26.             GameObject.Instantiate(Tankbaozha,transform.position+Vector3.up,transform.rotation);
  27.             GameObject.Destroy(this.gameObject);
  28. #if UNITY_EDITOR
  29.             UnityEditor.EditorApplication.isPlaying = false;
  30. #else
  31.                 Application.Quit();
  32. #endif
  33.         }
  34.     }
复制代码
3.tank触发到tank,调用2中天生的脚本
  1. public void OnTriggerEnter(Collider other)
  2. {
  3.      if (SheelExplosionPrefab != null)
  4.      {
  5.          GameObject.Instantiate(SheelExplosionPrefab, transform.position, transform.rotation);
  6.      }
  7.      if(other.tag=="Tank")
  8.      {
  9.          other.SendMessage("HurtHealthy");//即调用的方法
  10.      }
  11. }
复制代码


十.相机跟随

原理:相机与两坦克的中心保持肯定的向量关系,同时尚有近大远小的视觉结果
1.算出两坦克的中心点与摄像机坐标的向量差。


2.包管摄像机始终与中心点有个类似向量差


3.当坦克间距变小时,摄像头视角变小;反之,摄像头变大




十一.添加音效,音乐

1.配景音乐
(1)创建一个空物体,定名为:Music

(2)在空物体上添加组件audio source

(3)在组件上添加配景音乐

(4)举行底子设置即可

2.子弹音效:每次发射都会启动
原理:一样的添加audio source组件用来存储音效,每次在实例化子弹的时间,启动音效



十二.标题

1.大概出现的标题1:Assembly-CSharp-Editor渲染函数老旧逾期了。

办理方案:更换函数,下面是更换之后的代码:(复制粘贴即可)
  1. using System;
  2. using UnityEditor;
  3. using UnityEngine;
  4. namespace UnityStandardAssets.ImageEffects
  5. {
  6.     [CustomEditor(typeof(ColorCorrectionLookup))]
  7.     class ColorCorrectionLookupEditor : Editor
  8.     {
  9.         SerializedObject serObj;
  10.         void OnEnable()
  11.         {
  12.             serObj = new SerializedObject(target);
  13.         }
  14.         private Texture2D tempClutTex2D;
  15.         public override void OnInspectorGUI()
  16.         {
  17.             serObj.Update();
  18.             EditorGUILayout.LabelField("Converts textures into color lookup volumes (for grading)", EditorStyles.miniLabel);
  19.             //EditorGUILayout.LabelField("Change Lookup Texture (LUT):");
  20.             //EditorGUILayout.BeginHorizontal ();
  21.             //Rect r = GUILayoutUtility.GetAspectRect(1.0ff);
  22.             Rect r; Texture2D t;
  23.             //EditorGUILayout.Space();
  24.             tempClutTex2D = EditorGUILayout.ObjectField(" Based on", tempClutTex2D, typeof(Texture2D), false) as Texture2D;
  25.             if (tempClutTex2D == null)
  26.             {
  27.                 t = AssetDatabase.LoadMainAssetAtPath(((ColorCorrectionLookup)target).basedOnTempTex) as Texture2D;
  28.                 if (t) tempClutTex2D = t;
  29.             }
  30.             Texture2D tex = tempClutTex2D;
  31.             if (tex && (target as ColorCorrectionLookup).basedOnTempTex != AssetDatabase.GetAssetPath(tex))
  32.             {
  33.                 EditorGUILayout.Separator();
  34.                 if (!(target as ColorCorrectionLookup).ValidDimensions(tex))
  35.                 {
  36.                     EditorGUILayout.HelpBox("Invalid texture dimensions!\nPick another texture or adjust dimension to e.g. 256x16.", MessageType.Warning);
  37.                 }
  38.                 else if (GUILayout.Button("Convert and Apply"))
  39.                 {
  40.                     string path = AssetDatabase.GetAssetPath(tex);
  41.                     TextureImporter textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
  42.                     bool doImport = textureImporter.isReadable == false;
  43.                     if (textureImporter.mipmapEnabled == true)
  44.                     {
  45.                         doImport = true;
  46.                     }
  47.                     // 修改:检查纹理压缩格式
  48.                     if (textureImporter.textureCompression != TextureImporterCompression.Uncompressed)
  49.                     {
  50.                         doImport = true;
  51.                     }
  52.                     if (doImport)
  53.                     {
  54.                         textureImporter.isReadable = true;
  55.                         textureImporter.mipmapEnabled = false;
  56.                         // 修改:设置纹理压缩格式为无压缩
  57.                         textureImporter.textureCompression = TextureImporterCompression.Uncompressed;
  58.                         AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
  59.                         //tex = AssetDatabase.LoadMainAssetAtPath(path);
  60.                     }
  61.                     (target as ColorCorrectionLookup).Convert(tex, path);
  62.                 }
  63.             }
  64.             if ((target as ColorCorrectionLookup).basedOnTempTex != "")
  65.             {
  66.                 EditorGUILayout.HelpBox("Using " + (target as ColorCorrectionLookup).basedOnTempTex, MessageType.Info);
  67.                 t = AssetDatabase.LoadMainAssetAtPath(((ColorCorrectionLookup)target).basedOnTempTex) as Texture2D;
  68.                 if (t)
  69.                 {
  70.                     r = GUILayoutUtility.GetLastRect();
  71.                     r = GUILayoutUtility.GetRect(r.width, 20);
  72.                     r.x += r.width * 0.05f / 2.0f;
  73.                     r.width *= 0.95f;
  74.                     GUI.DrawTexture(r, t);
  75.                     GUILayoutUtility.GetRect(r.width, 4);
  76.                 }
  77.             }
  78.             //EditorGUILayout.EndHorizontal ();
  79.             serObj.ApplyModifiedProperties();
  80.         }
  81.     }
  82. }
复制代码


十三.结语

        《Tank_Battle》不但是一款具有娱乐性的游戏,也是一个良好的 Unity 开发实践项目。对于初学者来说,它展示了怎样使用 Unity 引擎举行场景搭建、对象控制、碰撞检测和殊效实现等底子开发技能;对于有肯定履历的开发者,也可以从中获取关于双人对战游戏操持和实现的思绪和方法。同时,项目还提供了大概出现标题标办理方案,有助于开发者在碰到类似标题时快速办理。
 
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表