打飞机战斗模块:
一、场景管理:
1.双方进入场景效果(例如:依次飞入)
关于动画,这里我们使用的是DoTween组件,具体的使用方法可以看我之前的博客:
http://blog.csdn.net/linshuhe1/article/details/51331569
2.战斗结束到下次战斗开始过度效果(例如:屏幕渐黑,胜利一方的飞机飞出屏幕显示范围)
黑幕效果:也是使用Plane组件,但是此时使用的材质所绑定的Shader类型,我们需要自行编写Shader文件,然后在Plane上绑定一个脚本,用于控制Shader中Color属性的透明度值的渐变效果
3.背景图效果(轮滚)
实现方式:两个Plane绑定一个脚本,Update方法中渐变坐标,到达某个阈值时重置坐标,两者轮流在屏幕中,Plane的大小至少要大于屏幕显示范围(防止背景不连续),创建一个Legacy Shaders/Diffuse类型的材质球Material,并拖过拖拽绑定材质上的图片,将材质球通过拖拽填充到Plane中的Mesh Renderer的Material属性上
切换背景图:通过Resources.Load
二、技能系统:
1.被动技能:也是自动战斗的AI
首先是攻击对象的选择逻辑,按照设计来说,攻击顺序是:先攻击对位上的对手,对位没有对手就攻击附近距离最近的,距离一样的话选择血量较高的。
2.Buff:伤害、回血等
新建一个BaseBuffer脚本,所有的Buff消息都发送的这个脚本是统一进行处理,Buff消息必须包含几个基本的信息:Buff的影响对象、Buff类型、Buff属性值、Buff的发出对象的属性(只是属性,并非对象实体,反正Buff还没还没作用完之前其发出对象就已经被销毁了,这样容易导致空对象引用的错误)
3.血量条:
关于血条实现的方式主要有两种,一种是直接把血条设计成3D场景中的一个对象绑定在英雄身上,并设置血条实时对准相机方向;另一种就是通过将3D空间中英雄的坐标转换为2D空间上的坐标,然后使用2D组件建立血条,并在Update中实时获取英雄的3D坐标转换后的2D坐标,并赋值给血条。
4.子弹系统:
先在Hierarchy中右键Create Empty建立一个空对象命名为Bullet,然后在其下创建一个2D对象Sprite(用于显示子弹的图片)命名为BulletSprite:
由于子弹进行攻击行为实际上就是与攻击对象发生碰撞事件,所以子弹需要添加碰撞组件Box Collider,可以根据子弹图片或者模型的大小调整碰撞框的大小:
每个子弹我们都需要绑定一个脚本用于定义子弹的一些基本属性、处理碰撞事件以及控制子弹的运动和消失等,这里我们创建了一个Bullet.cs脚本,关键在于重写OnTriggerEnter(Colliderother)方法,这是发生碰撞事件时会触发的方法,即我们所有关于碰撞事件的处理都写在这里即可,其中other为被碰撞的目标对象:
///
/// 子弹与飞机发生碰撞框事件
///
/// Other.
protected void OnTriggerEnter(Collider other)
{
//对自己战队无效
if (this.tag == other.tag)
return;
//子弹消失
Destroy(gameObject);
//发生buff消息
DataStructs.DemageData demage_data = new DataStructs.DemageData();
demage_data.target = other.transform;
demage_data.type = 0;
demage_data.num = power;
BaseBuff.ReceiveDemage(demage_data);
}
至于子弹的运动,即子弹空间位置的变化,在Update中进行动态修改localPosition来实现,具体思路可以是设定一个方向向量,即一个Vector3类型的数据,用速度向量乘以速度值再乘以时长,即得到空间位移量,再叠加到子弹原位置上即可得到新的位置,也可以限定超过某个范围时子弹自动销毁(提高效率):
///
/// 子弹位置变化
///
void Update () {
//游戏暂停
if (BattleManager.Instance.IsPause == true || IsPause == true)
return;
//mDirection为方向向量,speed为速度值
var position = mTransform.localPosition + mDirection * speed * Time.deltaTime;
if (position.z <= -7.11) {
Destroy(gameObject);
return;
}
mTransform.localPosition = position;
}
5.主动技能:大招(例如:突进、换位、长按)
手势识别:OnMouseDown、OnMouseUp、OnMouseDrag
using UnityEngine;
using System.Collections;
public class ActorHandleComponent : MonoBehaviour {
private Vector3 _vec3TargetScreenSpace;// 目标物体的屏幕空间坐标
private Vector3 _vec3TargetWorldSpace;// 目标物体的世界空间坐标
private static Transform Original_Trans;//未拖动前的位置
private Transform _trans;// 目标物体的空间变换组件
private Vector3 _vec3MouseScreenSpace;// 鼠标的屏幕空间坐标
private Vector3 _vec3Offset;// 偏移
private Camera[] mycamer;
private Camera selfCamer;
///
/// 三种手势识别
///
public enum HandleType {
SlideUp, //上滑
ChangePosition, //换位
LongPress //长按
}
void Awake( ) { _trans = transform; }
// Use this for initialization
void Start()
{
mycamer = new Camera[5];
self = transform.GetComponent();
Original_Trans = BattleManager.Instance.M_Pos[0];
Camera.GetAllCameras(mycamer);
foreach (Camera a in mycamer)
{
if (a != null)
{
if (a.tag == "UICamera")
{
//获取UICamera
selfCamer = a;
}
}
}
}
IEnumerator OnMouseDown( )
{
Debug.Log("鼠标消息*****************************OnMouseDown");
// 把目标物体的世界空间坐标转换到它自身的屏幕空间坐标
_vec3TargetScreenSpace = selfCamer.WorldToScreenPoint(_trans.position);
// 存储鼠标的屏幕空间坐标(Z值使用目标物体的屏幕空间坐标)
_vec3MouseScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, _vec3TargetScreenSpace.z);
// 计算目标物体与鼠标物体在世界空间中的偏移量
_vec3Offset = _trans.position - selfCamer.ScreenToWorldPoint(_vec3MouseScreenSpace);
// 鼠标左键按下
while ( Input.GetMouseButton(0) ) {
// 等待固定更新
yield return new WaitForFixedUpdate();
}
}
IEnumerator OnMouseUp()
{
Debug.Log(_trans.localPosition+"鼠标消息*****************************OnMouseUp:"+Original_Trans.localPosition);
if ((_trans.localPosition.z - Original_Trans.localPosition.z >= 0.7) && Mathf.Abs(_trans.localPosition.x - Original_Trans.localPosition.x) <= 0.5) {
Debug.Log("OnMouseUp==============上滑");
}
// 等待固定更新
yield return new WaitForFixedUpdate();
}
IEnumerator OnMouseDrag()
{
Debug.Log("鼠标消息*****************************OnMouseDrag");
// 存储鼠标的屏幕空间坐标(Z值使用目标物体的屏幕空间坐标)
_vec3MouseScreenSpace = new Vector3(Input.mousePosition.x, Input.mousePosition.y, _vec3TargetScreenSpace.z);
// 把鼠标的屏幕空间坐标转换到世界空间坐标(Z值使用目标物体的屏幕空间坐标),加上偏移量,以此作为目标物体的世界空间坐标
_vec3TargetWorldSpace = selfCamer.ScreenToWorldPoint(_vec3MouseScreenSpace) + _vec3Offset;
// 更新目标物体的世界空间坐标
_trans.position = _vec3TargetWorldSpace;
// 等待固定更新
yield return new WaitForFixedUpdate();
}
// Update is called once per frame
void Update () {
}
}
三、对象池:
由于在战斗场景中,我们需要频繁地创建飞机对象和子弹对象以及各种特效,假如不使用对象池,那么如此频繁的对象创建和销毁操作势必导致内存占用过高,在一些移动设备上也会出现设备发热严重以及闪退现象,为了避免这样的事情发生,我们就需要创建战斗场景中的对象池,对象销毁时放到对象池中,下次使用时直接从池子中获取对象进行复用,对象不够时再创建新对象,这样能大大提高游戏性能。我在这里使用第三方插件PoolManager来设计自己的对象池:
1.获取对象池:
private SpawnPool mActors_Pool;
mActors_Pool = PoolManager.Pools["ActorsAndBullets"];
2.获取对象的方法:
Transform bulletPrefab = mActors_Pool.prefabs["Bullet"];
Transform bullet = mActors_Pool.Spawn(bulletPrefab);
3.销毁对象的方法:
mActors_Pool.Despawn(bullet);