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

打飞机战斗模块:

一、场景管理:

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("路径")加载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:

        Unity学习笔记12——打飞机战斗模块_第1张图片    Unity学习笔记12——打飞机战斗模块_第2张图片

        由于子弹进行攻击行为实际上就是与攻击对象发生碰撞事件,所以子弹需要添加碰撞组件Box Collider,可以根据子弹图片或者模型的大小调整碰撞框的大小:

        Unity学习笔记12——打飞机战斗模块_第3张图片

        每个子弹我们都需要绑定一个脚本用于定义子弹的一些基本属性、处理碰撞事件以及控制子弹的运动和消失等,这里我们创建了一个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);



你可能感兴趣的:(Unity3D游戏开发,Unity学习笔记)