您的位置:首页 > 移动开发 > Unity3D

Unity学习笔记12——打飞机战斗模块

2016-05-07 15:00 706 查看
打飞机战斗模块:
一、场景管理:

1.双方进入场景效果(例如:依次飞入)

关于动画,这里我们使用的是DoTween组件,具体的使用方法可以看我之前的博客:

/article/7736326.html

2.战斗结束到下次战斗开始过度效果(例如:屏幕渐黑,胜利一方的飞机飞出屏幕显示范围)

黑幕效果:也是使用Plane组件,但是此时使用的材质所绑定的Shader类型,我们需要自行编写Shader文件,然后在Plane上绑定一个脚本,用于控制Shader中Color属性的透明度值的渐变效果

3.背景图效果(轮滚)

实现方式:两个Plane绑定一个脚本,Update方法中渐变坐标,到达某个阈值时重置坐标,两者轮流在屏幕中,Plane的大小至少要大于屏幕显示范围(防止背景不连续),创建一个Legacy Shaders/Diffuse类型的材质球Material,并拖过拖拽绑定材质上的图片,将材质球通过拖拽填充到Plane中的Mesh Renderer的Material属性上

切换背景图:通过Resources.Load<Texture>("路径")加载Resources文件夹下面指定路径的Texture属性的图片文件,将Texture复制给Mesh Renderer组件的material.mainTexture属性,即可切换背景图

二、技能系统:

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为被碰撞的目标对象:

/// <summary>
/// 子弹与飞机发生碰撞框事件
/// </summary>
/// <param name="other">Other.</param>
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类型的数据,用速度向量乘以速度值再乘以时长,即得到空间位移量,再叠加到子弹原位置上即可得到新的位置,也可以限定超过某个范围时子弹自动销毁(提高效率):

/// <summary>
/// 子弹位置变化
/// </summary>
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;

/// <summary>
/// 三种手势识别
/// </summary>
public enum HandleType {
SlideUp,        //上滑
ChangePosition, //换位
LongPress       //长按
}

void Awake( ) { _trans = transform; }

// Use this for initialization
void Start()
{
mycamer = new Camera[5];
self = transform.GetComponent<Actor>();
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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: