花了接近两天,试着将已近有的资源用上,开发出了一个简单的游戏。小小地总结下,理清下思路。要制作一个游戏,前期的准备是必不可少的,比如声音资源(AudioClips),一些模型(Models),一些材质(Materials)都是需要制作完成的,想要成为一个独立的游戏开发制作者,必须学会这些东西,比如建模的3dMax,玛雅之类的一些常用的软件,还必须有相当的美术功底。不过,在公司里大家都各司其职吧。
有了这些东西,那么就是要实现程序控制的问题了。
首先是将游戏场景布置好,将坦克模型拖入游戏场景中去,将车位的行走特效放到坦克模型下,使得特效属于坦克。
然后用刚体组件,控制小车行走和转向。在坦克TankMove类中,实现以下代码来控制小车的运动:
public int Speed=10;
public int AngularSpeed=10;
public int NumControl = 1;//增加编号来控制不同的坦克
private Rigidbody _rigidboyCar;
void start()
{
_rigidboyCar = GetComponent<Rigidbody>();
}
void Updata()
{
//得到键盘上的方向输入,值在-1到1之间变化
//HorizontalPlayer1只能由这asdw几个键控制,HorizontalPlayer2由箭头方向键控制。详情见Eidit->project settings->input
float keyNumQh = Input.GetAxis("VerticalPlayer" + NumControl);
//velocity施加速度,transform.forward前后移动
_rigidboyCar.velocity = transform.forward * keyNumQh * Speed;
//左右
float keyNumZy = Input.GetAxis("HorizontalPlayer"+NumControl);
_rigidboyCar.angularVelocity = transform.up*keyNumZy*AngularSpeed;
}
然后在炮筒口位置添加一个空的游戏对象,以便在这里实例化子弹,,通过制定按键进行子弹的发射,在TankFire类中实现下面的代码:
`
private Transform _firePosition;//子弹位置
public GameObject Shell;//子弹
public KeyCode Key = KeyCode.Space;//space按键控制发射
public int FireSpeed = 15;//子弹速度
void Start ()
{
_firePosition = transform.Find("FirePositon");//得到指定名字游戏对象的位置
}
void Update () {
if (Input.GetKeyDown(Key))//按键触发实例化
{
var shellFire= Instantiate(Shell, _firePosition.position, _firePosition.rotation) as GameObject ;//实例化,在指定位置创建子弹
if (shellFire != null)
shellFire.GetComponent<Rigidbody>().velocity = transform.forward*FireSpeed;//通过刚体发射子弹
}
}
那么子弹可以发射了,但是发射出去并不爆炸,那么如何控制子弹的爆炸,以及触发爆炸特效?答案是,利用在子弹上添加Capule Collider组件,控制子弹的碰撞检测,另外给子弹添加刚体控件,控制子弹的下落,在ShellExplousion类中实现:
public GameObject ShellExpol;//爆炸特效对象
//碰撞检测
public void OnTriggerEnter(Collider collider)
{
Instantiate(ShellExpol, transform.position, transform.rotation);//触发爆炸特效
Destroy(this.gameObject);//销毁子弹
if (collider.tag=="TANK")
{
//如果子弹碰撞到的是坦克的话,给坦克发送消息,控制血量
collider.SendMessage("TakeDamege");
}
}
接下来,给坦克添加标签tag,以便于子弹判断子弹碰撞的是坦克,来控制坦克血量的扣减,最后坦克血量为0后,销毁目标坦克。在控制坦克血量的类TankHealth中,实现下面代码:
public float Hp = 100;
public GameObject TankExplosion;
[CanBeNull] public Slider HpSlider;//血条,其size为0到1,0为完全不填充,1为完全填充
private const float HpTotal = 100;
private float _size;//当前血量/100
private void TakeDamege()
{
if (Hp <= 0)
return;
Hp -= Random.Range(0, 20);//0到20随机扣血
if (HpSlider != null) HpSlider.value = Hp / HpTotal;//血条减少
if (Hp<=0)//死亡,tank爆炸
{
Instantiate(TankExplosion, transform.position+Vector3.up, transform.rotation);//当前坦克的位置
Destroy(this.gameObject);
}
}
另外游戏中是两个坦克,如何控制相机跟随两个坦克呢?通过得到初始时,得到两个坦克之间与相机的偏移值,然后相机的位置等于偏移值加上两个坦克之间的值除2。在相机对象下,添加Follow类脚本(组件)中实现下面代码:
public Transform Player1;
public Transform Player2;
private Vector3 _offset;
private Camera _camera;
void Start ()
{
_offset = transform.position - (Player1.position + Player2.position)/2;//两个坦克间初始位置的偏移量,以后相机随时保持这个偏移量。
_camera = GetComponent<Camera>();
}
void Update ()
{
if (Player1==null||Player2==null ) return; ;
transform.position = _offset + (Player1.position + Player2.position)/2;
float distance = Vector3.Distance(Player1.position, Player2.position);
float size = distance*0.58f;//两个坦克位置的距离和相机size的比例为0.4,可以使得相机size随着两者距离改变,从而可以看得清楚
if (size>=10)
{
_camera.orthographicSize = size;
}
else
{
_camera.orthographicSize = 10;
}
}
到这里,基本结束。主要有几点要注意:
- 要在哪个游戏对象上实现特点功能,就在相应的游戏对象上添加组件。比如控制坦克移动,就子在坦克游戏对象下添加控制运动的脚本。
- 有的功能类型,需要重复使用的游戏对象,可以将游戏对象保存成prefab
- transform类可以得到位置,刚体组件可以控制运动,
- collider.SendMessage(“消息名”);可以实现类间的消息传递
- 在声明public变量的时候,可以将相应对象拖入相应位置,实现初始化。
还有一些细节,在以后慢慢继续学吧。。
本文是Unity3D学习笔记,通过实际制作3D坦克大战游戏,介绍了从场景布置到游戏逻辑的实现过程。包括坦克移动、子弹发射、碰撞检测、血量管理以及相机跟随等关键步骤,强调了游戏对象组件使用、Prefab复用及公共变量初始化等技巧。

3271

被折叠的 条评论
为什么被折叠?



