项目实训--Unity多人游戏开发(十五、道具战)

emm关于聊天功能的闲话

聊天功能也是使用PhotonChat提供的API,比较方便的是参考demo,发消息的逻辑代码直接拿来用就好了。要注意目前pun版本的chat服务只有eu服务器。
然后本项目的聊天功能中UI是自主开发的。仿照英雄联盟的聊天样式,游戏内不会遮挡,并且一定时间没有消息后自动隐藏…

道具战游戏简介

部分资源是Unity官方商店(比如人物)、还有部分资源来自其他素材网站。

截图

生成角色。
在这里插入图片描述
随着时间场上生成了不少道具。
在这里插入图片描述
捡了一个隐身、导弹、地雷,还有瞬移突进技能。
在这里插入图片描述
按2发射导弹打坏木箱,附带粒子特效。
在这里插入图片描述

游戏功能

人物–控制系统、生命值系统、道具捡拾与使用系统。
整个场景–道具生成系统(道具悬浮效果)、草丛隐身机制。
道具–不同道具不同功能,其中有隐身道具要和草丛的隐身联动起来。
道具计划制作五个(导弹、地雷、恢复、隐身、疾步),额外制作一个冲刺位移技能。
其中隐身道具和进入草丛“隐身”的实现方式详见下一篇文章。


生成数有最大限制以控制游戏以适中的节奏进行,同时避免过多道具占用cpu资源。
但是currentCount的–有问题,不清楚原因。

关键代码

全局

PropsManager.cs:场景中道具生成器。

/// <summary>
    /// 控制道具的生成
    /// </summary>
    public class PropsManager : MonoBehaviour
    {
   
   
        public enum PropsType
        {
   
   
            None,
            MissileProp,  //炮弹
            LandmineProp, //地雷
            CloakProp,
            HealthBottleProp, //血瓶
            SpeedUpProp,//疾步
            FlashSkill
        }
        private string[] propsPrefabNameWithRandom
            = {
   
   "DroppedMissile", "DroppedMissile", "DroppedLandMine", "DroppedLandMine", "DroppedBottle", "DroppedRandomBox" };

        public static int mapSizeCanSpawn = 20;//default 20,用于随机范围
        public float spawnInterval = 4;//间隔:?秒一次
        private float currentTime = 4;
        public int spawnCountOneTime = 4;
        public int maxSpawnCountPermit = 20;//限制最大数量---弱限制,可19到19 + spawnCountOneTime。

        private static int currentCountInScene = 0;//当前场景中存在的数量

        private void Start()
        {
   
   
            if(!PhotonNetwork.IsMasterClient)
            {
   
   
                return;
            }
            maxSpawnCountPermit = PhotonNetwork.PlayerList.Length * 15;
        }

        private void Update()
        {
   
   
            //生成道具
            if(PhotonNetwork.IsMasterClient && PropsGameManager.instance.isGameStart)
            {
   
   
                //计时
                if(currentTime > 0)
                {
   
   
                    currentTime -= Time.deltaTime;
                }
                else
                {
   
   
                    //判断道具数是否到达上限
                    //if (currentCountInScene < maxSpawnCountPermit)
                    //{
   
   
                        for (int i = 0; i < spawnCountOneTime; i++)
                        {
   
   
                            /*
                            PhotonNetwork.Instantiate(
                                Const.PUN_PROPS_GAME_PREFABS_BASEPATH 
                                    + propsPrefabNameWithRandom[Random.Range(0, propsPrefabNameWithRandom.Length)]
                                , propsSpawnPoints[Random.Range(0, propsSpawnPoints.Length)].position
                                , Quaternion.identity);
                            */
                            Vector3 pos = new Vector3(Random.Range(-18f, 18f), 1, Random.Range(-18f, 18f));
                            PhotonNetwork.Instantiate(Const.PUN_PROPS_GAME_PREFABS_BASEPATH 
                                + propsPrefabNameWithRandom[Random.Range(0, propsPrefabNameWithRandom.Length)]
                                , pos
                                , Quaternion.identity);
                            currentCountInScene++;
                        }
                    //}
                    currentTime = spawnInterval;
                }
            }
        }

        public static void DecreaseCurrentCount()
        {
   
   
            currentCountInScene--;//TODO:线程是否安全
        }
    }

悬浮物道具

DroppedProps.cs:掉落物形式的道具(可捡状态,包含悬浮动作、保证生成在空旷处)

public class DroppedProps : MonoBehaviour//用dotween
    {
   
   
        public PropsManager.PropsType propType = PropsManager.PropsType.HealthBottleProp;
        private Vector3 startPos;
        void Start()
        {
   
   
            if(PhotonNetwork.IsMasterClient)
            {
   
   
                TestCollision();
            }
            Move();
        }

        //出生检测
        //静止物体没有刚体,通过物理检测来决定重新生成,同修改DroppedRandomProps脚本
        private void TestCollision()
        {
   
   
            float radius = 0.8f;
            Vector3 explosionPos = transform.position;
            Collider[] colliders = Physics.OverlapSphere(explosionPos, radius);
            foreach (Collider hit in colliders)
            {
   
   
                if (hit.gameObject == this.gameObject)
                {
   
   
                    Debug.Log("self collision");
                    continue;
                }
                if (hit.gameObject.tag.Equals("Barrier") || hit.gameObject.tag.Equals("WoodenBox")
                    || hit.gameObject.tag.Equals("Grass") || hit.gameObject.tag.Equals("DroppedProps"))
                {
   
   
                    float sphereRadius = (float)PropsManager.mapSizeCanSpawn;
                    Vector3 pos = new Vector3(Random.Range(-sphereRadius, sphereRadius), 1, Random.Range(-sphereRadius, sphereRadius));
                    if(PhotonNetwork.IsMasterClient)
                    {
   
   
                        Debug.Log("发生碰撞self 刷新");
                        PhotonNetwork.Instantiate(Const.PUN_PROPS_GAME_PREFABS_BASEPATH + gameObject.name.Replace("(Clone)", ""), pos, Quaternion.identity);
                        PhotonNetwork.Destroy(gameObject);
                        return;
                    }
                }
            }
        }

        //悬浮
        private void Move()
        {
   
   
            startPos = transform.position;
            transform.DOPath(new Vector3[] {
   
    startPos, transform.position + new Vector3(0, 0.5f, 0), startPos }, 2)//Vector3.up//new Vector3(0,0.5f,0)
                .SetLoops(-1, LoopType.Restart);
            transform.DOBlendableLocalRotateBy(new Vector3(0, 360, 0), 4f, RotateMode.FastBeyond360)//.DORotate(new Vector3(0, 360, 45), 3f, RotateMode.WorldAxisAdd)
                .SetLoops(-1, LoopType.Restart);//循环设置为-1为一直
        }
      
        //销毁写在人物里面,背包满了道具碰到不销毁
    }

DroppedRandomProps.cs:因为隐身和疾步一些道具没有合适的3d资源。统一用一个“问号箱子”,也就是随机道具。
DroppedProps.cs基本一样,多了一个随机确定被捡的道具。


实际道具

PropMissile.cs:导弹道具(施放道具,非掉落物形式,为玩家使用后的真实导弹物体)
包含碰撞(爆炸)检测。和初始化问题。初始化时主要为调整导弹朝向。
(导弹模型默认导弹头是z轴正向的,所以要把z轴正向转向发射方向)

public class PropMissile : MonoBehaviour
    {
   
   
        public Player Owner {
   
    get; private set; }
        public GameObject explosionParticle;


        public void Start()
        {
   
   
            Destroy(gameObject, 3.0f);
        }
        public void OnTriggerEnter(Collider collision)
        {
   
   
            Debug.Log(collision.gameObject.name + "eee");//TODO:有时候会碰到自己?
            if (collision.gameObject.tag.Equals("DroppedProps") || collision.gameObject.tag.Equals("Grass"))
            {
   
   
                return;
            }
            if (collision.gameObject.tag.Equals("Player") && collision.gameObject.GetComponent<PhotonView>().Owner == Owner)
            {
   
   
                return;
            }
            float radius = 3.0f;
            Vector3 explosionPos = transform.position;
            Collider[] colliders = Physics.OverlapSphere(explosionPos, radius);

            bool clipIsPlayed = false;//如果破坏掉木箱,此bool控制只播放一次音效
            foreach (Collider hit in colliders)
            {
   
   
                if (hit.gameObject.tag.Equals("Player"))//打到玩家
                {
   
   
                    //TODO:不能打到自己
                    if(Owner.NickName.Equals(hit.gameObject.GetComponent
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值