近期热门
Unity3D 实现攻击扣血的流程

[U3D] Unity3D 实现攻击扣血的流程

 !heats_icon! [复制链接]
21234 7 0 1 13年前
本帖最后由 A你 于 2012-5-8 17:22 编辑

这个流程主要实现以下功能:界面上显示玩家当前的总血量,当被其他玩家发射的子弹打中后,会减1格血,血量为0时判定为死亡,会重置玩家的位置到出生点,并且重设血量为最大血量。

实现这个逻辑,分了以下几个步骤。

1.维护玩家血量相关信息。

首先玩家血量要用图形化在界面上显示,首先需要在场景中建立一个GUITexture,这里起名为GUI_heart,来表示当前血量图片。为了控制血量的显示,为GUI_heartf附加了一个控制脚本,名为HeartControl.cs。这个脚本的内容如下:

  1. using UnityEngine;

  2. using System.Collections;


  3. public class HeartControl : MonoBehaviour {

  4.   public Texture2D[] heartImageArray;

  5.   private const int maxLives = 5;

  6.   private static int lives = maxLives;

  7.    public static void DecreaseLive()

  8.    {

  9.        lives--;

  10.       if(lives==0)

  11.        {
  12.            lives=maxLives;

  13.           PlayerManager.selfPlayer.position = GameObject.Find("SpwanPlayer").transform.position;
  14.       }

  15.    }

  16.    // Use this for initialization

  17.   void Start () {



  18.   }


  19.    // Update is called once per frame

  20.     void Update () {

  21.        if(PlayerManager.selfPlayer!=null)

  22.    {

  23.        guiTexture.enabled = true;

  24.          guiTexture.texture = heartImageArray[lives-1];

  25.         }

  26.     else

  27.      {

  28.           guiTexture.enabled = false;

  29.      }



  30.   }
  31. }
复制代码
这里heartImageArray表示不同血量所对应的血量图片,血量用心型图标来显示,5格血就是5颗心。把这个数组声明为public,可以在编辑器中,设置这个数组的尺寸,以及每个入口点所对应的图片,十分方便。

maxLives就是最大血量有5格血,lives是当前人物的血量。

在每帧更新函数Update()中,首先检查当前玩家的变量是否为空,为空可能是因为是Server端,这种情况下就不需要显示血量,因此将图片设为false:guiTexture.enabled = false;

如果不为空,那么将根据当前血量的值,把对应数组中的图片赋值给这个guiTexture当前的texture,这样就实现图片随血量值的变化而变化。

这里PlayerManager.selfPlayer中的PlayerManager我自己建立的一个全局的静态类,维护了唯一的静态变量private static Transform _selfplayer,代表客户端所对应的玩家自己。这个类可以被所有脚本所访问,访问起来十分方便,实现如下:

  1. using UnityEngine;

  2. using System.Collections;

  3. using System;



  4. public static class PlayerManager  {



  5. private static Transform _selfplayer = null;

  6. public static Transform selfPlayer

  7. {

  8.       get

  9.        {

  10.           return _selfplayer;

  11.        }

  12.        set

  13.        {

  14.            _selfplayer = value;



  15.      }

  16.    }



  17. }
复制代码
后期随着逻辑的复杂,可以为这个脚本的玩家增加更多的数据来维护。

      然后是DecreaseLive函数,这个函数可以被外部所调用,给玩家减血,调用后,自动扣除一滴血,为0时,正如规定的一样,重设玩家血量为最大血量,并且找到重生点的位置,将玩家位置重置。

2.控制子弹打中玩家的逻辑

实现大体流程是先给玩家的人物身上附加一个释放子弹的脚本,当客户端自己的玩家按键触发技能时,就调用一个网络上的RPC,告诉所有客户端和服务器在本地创建一个飞行的子弹。并且在这个人物脚本里添加一个响应人物碰撞的事件函数,然后检查是不是碰撞的对象是子弹,而且不是这个人物所发射的,如果检测成功,就调用HeartControl脚本的减血函数。

这个脚本名为Shoot.cs,实现如下:

  1. using UnityEngine;

  2. using System.Collections;



  3. public class Shoot : MonoBehaviour

  4. {

  5.   public Texture skillTex1;

  6.    public Texture skillTex2;

  7.     public Transform bulletPrefab;

  8.     public Transform explosionEffect;

  9.     public AnimationClip attackAnim;



  10.    // Use this for initialization

  11.    void Start ()

  12.     {



  13.   }



  14.     // Update is called once per frame

  15.    void Update ()

  16.   {

  17.        if (networkView.isMine && Input.GetKeyUp ("2")) {

  18.            ShootBullet ();



  19.      }

  20.           if (networkView.isMine && Input.GetKeyUp ("3")) {

  21.           ExplosiveEffect();



  22.        }


  23.   }


  24.    void OnGUI ()

  25.     {

  26.        if (networkView.isMine)

  27.        {

  28.            if(GUI.Button (new Rect ((float)(0.5*Screen.width-60), (float)(Screen.height-60), 60, 60), skillTex1))

  29.            {

  30.           ShootBullet();}


  31.            if(GUI.Button(new Rect((float)0.5*Screen.width,(float)Screen.height-60,60,60),skillTex2))

  32.             {
  33.              ExplosiveEffect();

  34.            }

  35.       }



  36.    }



  37.    void OnCollisionEnter(Collision collisionInfo)

  38.    {





  39.        if(collisionInfo.gameObject.tag=="bullet" )

  40.        {

  41.            BulletScript bs = (BulletScript)collisionInfo.gameObject.GetComponent("BulletScript");

  42.            if(bs.Owner != gameObject)

  43.            {

  44.                print("OnCollisionEnter"+collisionInfo.gameObject.name);

  45.                Destroy(collisionInfo.gameObject);




  46.                if(!networkView.isMine)
  47.                     return;

  48.                 HeartControl.DecreaseLive();
  49.            }






  50.         }

  51.    }
  52.    void ExplosiveEffect()

  53.    {
  54.       networkView.RPC("SpwanExplosion",RPCMode.All);

  55.       SendMessage("PlayAnimation_Attack");

  56.   }
  57.     void ShootBullet()

  58.    {
  59.        networkView.RPC("SpawnBullet",RPCMode.All);

  60.   }

  61.     [RPC]

  62.   void SpawnBullet ()

  63.    {

  64.    Vector3 forward = transform.TransformDirection (Vector3.forward);

  65.     Transform effectPoint = transform.Find ("effectPoint");

  66.       PrefabDepends preScript = (PrefabDepends)GameObject.Find("GameObject_GlobalController").GetComponent("PrefabDepends");

  67.       if (effectPoint) {

  68.         Transform bullet = (Transform)Instantiate (preScript.bulletPrefab, effectPoint.position, Quaternion.identity);

  69.             bullet.rigidbody.AddForce (forward * 2000);

  70.             BulletScript bs = (BulletScript)bullet.GetComponent("BulletScript");

  71.           bs.Owner = gameObject;

  72.     }

  73.   }

  74.   [RPC]

  75.   void SpwanExplosion()

  76.    {

  77.       Vector3 forward = transform.TransformDirection (Vector3.forward);

  78.       Transform effectPoint = transform.Find ("effectPoint2");

  79.       if (effectPoint) {

  80.            //Object temp = Network.Instantiate (bulletPrefab, effectPoint.position, Quaternion.identity, 0);

  81.         Transform explosion = (Transform)Instantiate (explosionEffect, effectPoint.position, Quaternion.identity);

  82.        //Network.Instantiate(bulletPrefab,transform.Find("effectPoint").position,Quaternion.identity,0);

  83.         }

  84. }

  85. }
复制代码
SpawnBullet就是调用的RPC call,在这里除了用子弹的prefab创建出子弹附加初始速度,还给子弹的脚本BulletScript的一个变量Owner赋值为脚本所附加到的玩家,这是为了判断这个子弹是哪个玩家发出用的。

碰撞检测的函数是OnCollisionEnter,要想触发这个函数,人物身上需要有一个Collider控件,而CharacterController是没有用的。所有的子弹都设为了名为"bullet"的tag,所以在这里检测,如果碰撞的对象是bullet,并且子弹上的脚本的变量Owner不是这个玩家自己,说明被别人的子弹击中,就先销毁本地创建出来的子弹,然后判断如果这个玩家是这个客户端所对应的,就进行减血。这个判断是必要的,因为这里的血量是全局静态的,只有一份代表自己,其他玩家被子弹攻击到了,不需要更新自己的血量。

0
点赞
0
打赏
1
添加到收藏夹

0

点击复制链接

使用微信扫码分享
一次扣10个券
全部评论7
您需要登录后才可以回帖 登录

{:7_275:}我要学习!
12年前  ·  8楼
回复

使用道具 举报

谢谢楼主,楼主幸苦了。
12年前  ·  7楼
回复

使用道具 举报

{:soso_e102:}
12年前  ·  6楼
回复

使用道具 举报




Network.Instantiate不知为啥服务器报错找不到资源
12年前  ·  5楼
回复

使用道具 举报

谢谢楼主,楼主幸苦了。
13年前  ·  4楼
回复

使用道具 举报

卧虎藏龙哦,高手真多
我想我是一天也不能离开cgjoy游戏动画论坛。
13年前  ·  3楼
回复

使用道具 举报

懂的人一看就是非常有用啊
13年前  ·  2楼
回复

使用道具 举报

您当前使用的浏览器IE内核版本过低会导致网站显示错误

请使用高速内核浏览器或其他浏览器