• Road Crossing Game Template 学习


    using UnityEngine;
    using System;
    
    namespace RoadCrossing.Types
    {
        /// <summary>
        /// 小路
        /// </summary>
        [Serializable]
        public class Lane
        {
            /// <summary>
            /// 小路相关的游戏物体
            /// </summary>
            public Transform laneObject;
            /// <summary>
            /// 生成这条路的几率
            /// </summary>
            public int laneChance = 1;
            /// <summary>
            /// 小路的宽度
            /// </summary>
            public float laneWidth = 1;
            /// <summary>
            /// 生成物品的几率
            /// </summary>
            public float itemChance = 1;
        }
    }
    Lane
    using UnityEngine;
    using System;
    namespace RoadCrossing.Types
    {
        /// <summary>
        /// 掉落物品
        /// </summary>
        [Serializable]
        public class ObjectDrop
        {
            /// <summary>
            /// 掉落物品
            /// </summary>
            public Transform droppedObject;
            
            /// <summary>
            /// 掉落几率
            /// </summary>
            public int dropChance = 1;
        }
    }
    ObjectDrop
    using UnityEngine;
    using System;
    
    namespace RoadCrossing.Types
    {
        /// <summary>
        /// 商店道具
        /// </summary>
        [Serializable]
        public class ShopItem
        {
            /// <summary>
            /// 这个道具关联的按钮
            /// </summary>
            public Transform itemButton;
            
            /// <summary>
            /// 解锁状态,0 未解锁 1 已解锁
            /// </summary>
            public int lockState = 0;
            
            /// <summary>
            /// 解锁这个道具的花费
            /// </summary>
            public int costToUnlock = 100;
            
            /// <summary>
            /// 这个道具在存档中的键名
            /// </summary>
            public string playerPrefsName = "FroggyUnlock";
        }
    }
    ShopItem
    using System;
    
    namespace RoadCrossing.Types
    {
        /// <summary>
        /// 接触后调用的函数信息
        /// </summary>
        [Serializable]
        public class TouchFunction
        {
            /// <summary>
            /// 调用的函数名称
            /// </summary>
            public string functionName = "CancelMove";
            
            /// <summary>
            /// 在哪个目标上调用函数
            /// </summary>
            public string targetTag = "Player";
            
            /// <summary>
            /// 传递给函数的参数
            /// </summary>
            public float functionParameter = 0;
        }
    }
    TouchFunction
    using UnityEngine;
    using RoadCrossing.Types;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 能与玩家交互的块,可以是岩石,墙,敌人,金币
        /// </summary>
        public class RCGBlock : MonoBehaviour
        {
            /// <summary>
            /// 能够接触这个块的物体的标签
            /// </summary>
            public string touchTargetTag = "Player";
        
            /// <summary>
            /// 这个块被目标接触后调用的函数列表
            /// </summary>
            public TouchFunction[] touchFunctions;
        
            /// <summary>
            /// 经过多少次接触后删除这个物体
            /// </summary>
            public int removeAfterTouches = 0;
            /// <summary>
            /// 这个物体是否可以被移除
            /// </summary>
            internal bool  isRemovable = false;
        
            /// <summary>
            /// 当这个物体被接触后的动画剪辑
            /// </summary>
            public AnimationClip hitAnimation;
        
            /// <summary>
            /// 当这个物体被接触后的声音剪辑
            /// </summary>
            public AudioClip soundHit;
    
            /// <summary>
            /// AudioSource所属物体的标签
            /// </summary>
            public string soundSourceTag = "GameController";
        
            /// <summary>
            /// 物体死亡后创建的死亡的特效
            /// </summary>
            public Transform deathEffect;
        
    
            void Start()
            {
                if( removeAfterTouches > 0 )
                    isRemovable = true;
            }
        
            void OnTriggerEnter(Collider other)
            {    
                if( other.tag == touchTargetTag )
                {
                    //调用目标物体上的函数
                    foreach( var touchFunction in touchFunctions )
                    {
                        if( touchFunction.targetTag != string.Empty && touchFunction.functionName != string.Empty )
                        {
                            GameObject.FindGameObjectWithTag(touchFunction.targetTag).SendMessage(touchFunction.functionName, touchFunction.functionParameter);
                        }
                    }
                
                    //满足条件,播放动画
                    if( GetComponent<Animation>() && hitAnimation )
                    {
                        GetComponent<Animation>().Stop();
                        GetComponent<Animation>().Play(hitAnimation.name);
                    }
                
                    //满足条件,删除物体,创建死亡特效
                    if( isRemovable == true )
                    {
                        removeAfterTouches--;
                    
                        if( removeAfterTouches <= 0 )
                        {
                            if( deathEffect )
                                Instantiate(deathEffect, transform.position, Quaternion.identity);
                        
                            Destroy(gameObject);
                        }
                    }
                
                    //满足条件,播放声音
                    if( soundSourceTag != string.Empty && soundHit )
                        GameObject.FindGameObjectWithTag(soundSourceTag).GetComponent<AudioSource>().PlayOneShot(soundHit);
                }
            }
        }
    }
    RCGBlock
    using UnityEngine;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 控制上下左右点击的按钮(collider)
        /// </summary>
        public class RCGButtonFunction : MonoBehaviour
        {
            /// <summary>
            /// 要执行函数的物体
            /// </summary>
            public Transform functionTarget;
        
            /// <summary>
            /// 要执行的函数名称
            /// </summary>
            public string functionName;
        
            /// <summary>
            /// 传递给函数的参数
            /// </summary>
            public string functionParameter;
        
            /// <summary>
            /// 点击声音
            /// </summary>
            public AudioClip soundClick;
            /// <summary>
            /// AudioSource 所属的物体
            /// </summary>
            public Transform soundSource;
    
            void OnMouseDrag()
            {
                ExecuteFunction();
            }
        
            /// <summary>
            /// 执行函数
            /// </summary>
            void ExecuteFunction()
            {
                if( soundSource )
                    if( soundSource.GetComponent<AudioSource>() )
                        soundSource.GetComponent<AudioSource>().PlayOneShot(soundClick);
            
                if( functionName != string.Empty )
                {  
                    if( functionTarget )
                    {
                        functionTarget.SendMessage(functionName, functionParameter);
                    }
                }
            }
        }
    }
    RCGButtonFunction
    using System.Collections;
    using UnityEngine;
    using UnityEngine.UI;
    using RoadCrossing.Types;
    
    namespace RoadCrossing
    {
            
        /// <summary>
        /// 游戏控制
        /// </summary>
        public class RCGGameController : MonoBehaviour
        {
            /// <summary>
            /// 玩家物体列表
            /// </summary>
            public Transform[] playerObjects;
            /// <summary>
            /// 当前玩家物体索引
            /// </summary>
            public int currentPlayer;
        
            /// <summary>
            /// 跟随玩家的相机
            /// </summary>
            public Transform cameraObject;
    
            /// <summary>
            /// 控制玩家移动的按钮(collider),如果是滑动控制,这些物体会被禁用
            /// </summary>
            public Transform moveButtonsObject;
            
            /// <summary>
            /// 是否使用滑动控制
            /// </summary>
            public bool swipeControls = false;
            
            /// <summary>
            /// 滑动起点
            /// </summary>
            internal Vector3 swipeStart;
            /// <summary>
            /// 滑动终点
            /// </summary>
            internal Vector3 swipeEnd;
            
            public float swipeDistance = 10;
    
            /// <summary>
            /// 滑动命令取消前的等待时间
            /// </summary>
            public float swipeTimeout = 1;
            /// <summary>
            /// 
            /// </summary>
            internal float swipeTimeoutCount;
        
            /// <summary>
            /// 所有的小路预设列表
            /// </summary>
            public Lane[] lanes;
            internal Lane[] lanesList;    
        
            public ObjectDrop[] objectDrops;
            internal Transform[] objectDropList;
    
            public int objectDropOffset = 4;
        
            /// <summary>
            /// 游戏开始前与预创建的小路数量
            /// </summary>
            public int precreateLanes = 20;
            /// <summary>
            /// 下一条小路的位置
            /// </summary>
            internal float nextLanePosition = 1;
        
            /// <summary>
            /// 得分
            /// </summary>
            public int score = 0;
            /// <summary>
            /// 显示得分的文本
            /// </summary>
            public Transform scoreText;
            /// <summary>
            /// 最高分数
            /// </summary>
            internal int highScore = 0;
    
            /// <summary>
            /// 游戏中总共获得的分数
            /// </summary>
            public string coinsPlayerPrefs = "Coins";
        
            /// <summary>
            /// 游戏速度
            /// </summary>
            public float gameSpeed = 1;
        
            /// <summary>
            /// 玩家升级需要的点数
            /// </summary>
            public int levelUpEveryCoins = 5;
            /// <summary>
            /// 增加的分数
            /// </summary>
            internal int increaseCount = 0;
        
            /// <summary>
            /// 在玩家身后追逐玩家的物体
            /// </summary>
            public Transform deathLineObject;
            /// <summary>
            /// 追杀物体的移动速度
            /// </summary>
            public float deathLineSpeed = 1;
            /// <summary>
            /// 追杀物体每次增加的速度的值
            /// </summary>
            public float deathLineSpeedIncrease = 1;
            /// <summary>
            /// 追杀物体的最大移动速度
            /// </summary>
            public float deathLineSpeedMax = 1.5f;
    
            /// <summary>
            /// 游戏面板
            /// </summary>
            public Transform gameCanvas;
            /// <summary>
            /// 暂停面板
            /// </summary>
            public Transform pauseCanvas;
            /// <summary>
            /// 游戏结束面板
            /// </summary>
            public Transform gameOverCanvas;
        
            /// <summary>
            /// 游戏是否结束
            /// </summary>
            internal bool  isGameOver = false;
        
            /// <summary>
            /// 主目录场景
            /// </summary>
            public string mainMenuLevelName = "MainMenu";
        
            /// <summary>
            /// 升级声音
            /// </summary>
            public AudioClip soundLevelUp;
            /// <summary>
            /// 游戏结束声音
            /// </summary>
            public AudioClip soundGameOver;
        
            /// <summary>
            /// 使用AudioSource的物体的标签
            /// </summary>
            public string soundSourceTag = "GameController";
            /// <summary>
            /// 确认按钮
            /// </summary>
            public string confirmButton = "Submit";
        
            //暂停按钮
            public string pauseButton = "Cancel";
            /// <summary>
            /// 游戏是否暂停
            /// </summary>
            internal bool  isPaused = false;
            /// <summary>
            /// 
            /// </summary>
            internal int index = 0;
        
            void Start()
            {
                ChangeScore(0);
            
                //隐藏游戏结束面板
                if( gameOverCanvas )
                    gameOverCanvas.gameObject.SetActive(false);
            
                //获取存档中的最高分数
                highScore = PlayerPrefs.GetInt(Application.loadedLevelName + "_HighScore", 0);
            
                int totalLanes = 0;
                int totalLanesIndex = 0;
            
                for(index = 0; index < lanes.Length; index++)
                {
                    totalLanes += lanes[index].laneChance;
                }
            
                lanesList = new Lane[totalLanes];
            
                for(index = 0; index < lanes.Length; index++)
                {
                    int laneChanceCount = 0;
                
                    while( laneChanceCount < lanes[index].laneChance )
                    {
                        lanesList[totalLanesIndex] = lanes[index];
                    
                        laneChanceCount++;
                    
                        totalLanesIndex++;
                    }
                }
            
                int totalDrops = 0;
                int totalDropsIndex = 0;
            
                for(index = 0; index < objectDrops.Length; index++)
                {
                    totalDrops += objectDrops[index].dropChance;
                }
            
                objectDropList = new Transform[totalDrops];
            
                for(index = 0; index < objectDrops.Length; index++)
                {
                    int dropChanceCount = 0;
                
                    while( dropChanceCount < objectDrops[index].dropChance )
                    {
                        objectDropList[totalDropsIndex] = objectDrops[index].droppedObject;
                    
                        dropChanceCount++;
                    
                        totalDropsIndex++;
                    }
                }
    
                //从存档中获取当前玩家
                currentPlayer = PlayerPrefs.GetInt("CurrentPlayer", currentPlayer);
    
                SetPlayer(currentPlayer);
            
                if( cameraObject == null )
                    cameraObject = GameObject.FindGameObjectWithTag("MainCamera").transform;
            
                CreateLane(precreateLanes);
            
                
                Pause();
            }
        
            void Update()
            {
                if( isGameOver == true )
                {
                    if( Input.GetButtonDown(confirmButton) )
                    {
                        Restart();
                    }
                
                    if( Input.GetButtonDown(pauseButton) )
                    {
                        MainMenu();
                    }
                }
                else
                {
                    if( Input.GetButtonDown(pauseButton) )
                    {
                        if( isPaused == true )
                            Unpause();
                        else
                            Pause();
                    }
    
                    if ( swipeControls == true )
                    {
                        if ( swipeTimeoutCount > 0 )    swipeTimeoutCount -= Time.deltaTime;
                        
                        foreach ( Touch touch in Input.touches )
                        {
                            if ( touch.phase == TouchPhase.Began )
                            {
                                swipeStart = touch.position;
                                swipeEnd = touch.position;
                                
                                swipeTimeoutCount = swipeTimeout;
                            }
                            
                            if ( touch.phase == TouchPhase.Moved )
                            {
                                swipeEnd = touch.position;
                            }
                            
                            if( touch.phase == TouchPhase.Ended && swipeTimeoutCount > 0 )
                            {
                                if( (swipeStart.x - swipeEnd.x) > swipeDistance && (swipeStart.y - swipeEnd.y) < -swipeDistance )
                                {
                                    MovePlayer("left");
                                }
                                else if((swipeStart.x - swipeEnd.x) < -swipeDistance && (swipeStart.y - swipeEnd.y) > swipeDistance )
                                {
                                    MovePlayer("right");
                                }
                                else if((swipeStart.y - swipeEnd.y) < -swipeDistance && (swipeStart.x - swipeEnd.x) < -swipeDistance )
                                {
                                    MovePlayer("forward");
                                }
                                else if((swipeStart.y - swipeEnd.y) > swipeDistance && (swipeStart.x - swipeEnd.x) > swipeDistance )
                                {
                                    MovePlayer("backward");
                                }
                            }
                        }
                    }
                }
                
                if( nextLanePosition - cameraObject.position.x < precreateLanes )
                    CreateLane(1);
                
                if( cameraObject )
                {
                    if( playerObjects[currentPlayer] )
                        cameraObject.position = new Vector3(Mathf.Lerp(cameraObject.position.x, playerObjects[currentPlayer].position.x, Time.deltaTime * 3), 0, Mathf.Lerp(cameraObject.position.z, playerObjects[currentPlayer].position.z, Time.deltaTime * 3));
                
                    if( deathLineObject )
                    {
                        Vector3 newVector3 = deathLineObject.position;
    
                        if( cameraObject.position.x > deathLineObject.position.x )
                            newVector3.x = cameraObject.position.x;
    
                        if( isGameOver == false )
                            newVector3.x += deathLineSpeed * Time.deltaTime;
                
                        deathLineObject.position = newVector3;
                    }
                }
            }
        
            /// <summary>
            /// 创建小路
            /// </summary>
            /// <param name="laneCount"小路数量></param>
            void CreateLane(int laneCount)
            {
                while( laneCount > 0 )
                {
                    laneCount--;
                
                    int randomLane = Mathf.FloorToInt(Random.Range(0, lanesList.Length));
                
                    Transform newLane = Instantiate(lanesList[randomLane].laneObject, new Vector3(nextLanePosition, 0, 0), Quaternion.identity) as Transform;
    
                    if( Random.value < lanesList[randomLane].itemChance )
                    { 
                        Transform newObject = Instantiate(objectDropList[Mathf.FloorToInt(Random.Range(0, objectDropList.Length))]) as Transform;
    
                        Vector3 newVector = new Vector3();
    
                        newVector = newLane.position;
    
                        newVector.z += Mathf.Round(Random.Range(-objectDropOffset, objectDropOffset));
    
                        newObject.position = newVector;
                    }
                
                    nextLanePosition += lanesList[randomLane].laneWidth;
                }
            }
    
            /// <summary>
            /// 改变分数
            /// </summary>
            /// <param name="changeValue">改变的分数</param>
            void ChangeScore(int changeValue)
            {
    
                score += changeValue;
            
                //更新文本的分数显示
                if( scoreText )
                    scoreText.GetComponent<Text>().text = score.ToString();
            
                increaseCount += changeValue;
            
                //达到升级的条件,升级
                if( increaseCount >= levelUpEveryCoins )
                {
                    increaseCount -= levelUpEveryCoins;
                
                    LevelUp();
                }
            }
    
            /// <summary>
            /// 升级,并增加游戏难度
            /// </summary>
            void LevelUp()
            {
                //如果追杀物没有到达最大速度,增加它的速度
                if( deathLineSpeed + deathLineSpeedIncrease < deathLineSpeedMax )
                    deathLineSpeed += deathLineSpeedIncrease;    
    
                //播放升级声音
                if( soundSourceTag != string.Empty && soundLevelUp )
                    GameObject.FindGameObjectWithTag(soundSourceTag).GetComponent<AudioSource>().PlayOneShot(soundLevelUp);
            }
        
            /// <summary>
            /// 暂停游戏
            /// </summary>
            void Pause()
            {
                isPaused = true;
            
                Time.timeScale = 0;
            
                //显示暂停Canvas
                if( pauseCanvas )
                    pauseCanvas.gameObject.SetActive(true);
                //隐藏游戏Canvas
                if( gameCanvas )
                    gameCanvas.gameObject.SetActive(false);
            }
        
            /// <summary>
            /// 取消暂停
            /// </summary>
            void Unpause()
            {
                isPaused = false;
            
                Time.timeScale = gameSpeed;
            
                //隐藏暂停Canvas
                if( pauseCanvas )
                    pauseCanvas.gameObject.SetActive(false);
                //显示游戏Canvas
                if( gameCanvas )
                    gameCanvas.gameObject.SetActive(true);
            }
        
            /// <summary>
            /// 游戏结束协程
            /// </summary>
            /// <param name="delay">等待时间</param>
            IEnumerator GameOver(float delay)
            {
                yield return new WaitForSeconds(delay);
            
                isGameOver = true;
            
                //删除暂停面板
                if( pauseCanvas )
                    Destroy(pauseCanvas.gameObject);
                //删除游戏面板
                if( gameCanvas )
                    Destroy(gameCanvas.gameObject);
    
                //从存档中获取所有金币数量
                int totalCoins = PlayerPrefs.GetInt( coinsPlayerPrefs, 0);
                
                //添加本局游戏获得的得分
                totalCoins += score;
                
                //将新的总得分写入存档中
                PlayerPrefs.SetInt( coinsPlayerPrefs, totalCoins);
            
                if( gameOverCanvas )
                {
                    //激活游戏结束面板
                    gameOverCanvas.gameObject.SetActive(true);
                
                    //显示本次游戏得分
                    gameOverCanvas.Find("TextScore").GetComponent<Text>().text = "SCORE " + score.ToString();
                
                    //设置最高得分
                    if( score > highScore )
                    {
                        highScore = score;
                    
                        PlayerPrefs.SetInt(Application.loadedLevelName + "_HighScore", score);
                    }
                
                    //将最高得分显示在文本上
                    gameOverCanvas.Find("TextHighScore").GetComponent<Text>().text = "HIGH SCORE " + highScore.ToString();
                }
            }
        
            /// <summary>
            /// 重新开始
            /// </summary>
            void Restart()
            {
                Application.LoadLevel(Application.loadedLevelName);
            }
        
            /// <summary>
            /// 回到主目录
            /// </summary>
            void MainMenu()
            {
                Application.LoadLevel(mainMenuLevelName);
            }
    
            /// <summary>
            /// 根据玩家编号,激活选择的玩家
            /// </summary>
            /// <param name="playerNumber"></param>
            void SetPlayer( int playerNumber )
            {
                for(index = 0; index < playerObjects.Length; index++)
                {
                    if ( index != playerNumber )    
                        playerObjects[index].gameObject.SetActive(false);
                    else    
                        playerObjects[index].gameObject.SetActive(true);
                }
            }
    
            /// <summary>
            /// 移动玩家
            /// </summary>
            /// <param name="moveDirection">移动方向</param>
            void MovePlayer( string moveDirection )
            {
                if ( playerObjects[currentPlayer] )    playerObjects[currentPlayer].SendMessage("Move", moveDirection);
            }
        }
    }
    RCGGameController
    using UnityEngine;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 小路
        /// </summary>
        public class RCGLane : MonoBehaviour
        {
            /// <summary>
            /// transform缓存
            /// </summary>
            internal Transform thisTransform;
        
            /// <summary>
            /// 起始位置
            /// </summary>
            public Vector3 laneStart = new Vector3(0, 0, -7);
            /// <summary>
            /// 结束位置
            /// </summary>
            public Vector3 laneEnd = new Vector3(0, 0, 7);
        
            /// <summary>
            /// 小路上候选的移动物体数组
            /// </summary>
            public Transform[] movingObjects;
        
            /// <summary>
            /// 小路上的移动物体数组
            /// </summary>
            internal Transform[] movingObjectsList;
        
            /// <summary>
            /// 小路上允许存在的移动物体的数量范围
            /// </summary>
            public Vector2 movingObjectsNumber = new Vector2(1, 3);
    
            /// <summary>
            /// 移动物体之间的间隔
            /// </summary>
            public float minimumObjectGap = 1;
    
            /// <summary>
            /// 所有物体的移动速度范围
            /// </summary>
            public Vector2 moveSpeed = new Vector2(0.5f, 1);
        
            /// <summary>
            /// 物体的移动方向
            /// </summary>
            internal int moveDirection = 1;
    
            /// <summary>
            /// 是否随机方向
            /// </summary>
            public bool randomDirection = true;
        
            void Start()
            {
                thisTransform = transform;
            
                //满足条件改变移动方向
                if( randomDirection == true && Random.value > 0.5f )
                    moveDirection = -1;
    
                //随机选择移动速度
                moveSpeed.x = Random.Range(moveSpeed.x, moveSpeed.y);
            
                //计算路的长度
                float laneLength = Vector3.Distance(laneStart, laneEnd);
            
                //设置这条路上移动物体的数量
                int currentMovingObjectsNumber = Mathf.FloorToInt(Random.Range(movingObjectsNumber.x, movingObjectsNumber.y));
                
                //创建移动物体列表
                movingObjectsList = new Transform[currentMovingObjectsNumber];
    
                for(int index = 0; index < currentMovingObjectsNumber; index++)
                {
                    //创建一个随机的移动物体
                    Transform newMovingObject = Instantiate(movingObjects[Mathf.FloorToInt(Random.Range(0, movingObjects.Length))]) as Transform;
                
                    //在小路起点放置这个物体
                    newMovingObject.position = thisTransform.position + laneStart;
                    //让这个物体朝向路的终点
                    newMovingObject.LookAt(thisTransform.position + laneEnd);
    
                    newMovingObject.Translate(Vector3.forward * index * laneLength / currentMovingObjectsNumber, Space.Self);
    
                    newMovingObject.Translate(Vector3.forward * Random.Range(minimumObjectGap, laneLength / movingObjectsNumber.x - minimumObjectGap), Space.Self);
    
                    //将这个物体添加到移动物体列表
                    movingObjectsList[index] = newMovingObject;
                }
    
                foreach( Transform movingObject in movingObjectsList )
                {
                    //根据方向设置移动物体的朝向,起点或终点
                    if( moveDirection == 1 )
                        movingObject.LookAt(thisTransform.position + laneEnd);
                    else
                        movingObject.LookAt(thisTransform.position + laneStart);
                
                    //如果又动画组件,播放动画
                    if( movingObject.GetComponent<Animation>() )
                    {
                        //根据物体的移动速度设置动画的播放速度
                        movingObject.GetComponent<Animation>()[movingObject.GetComponent<Animation>().clip.name].speed = moveSpeed.x;
                    }
                }
            }
        
            void Update()
            {
                foreach( Transform movingObject in movingObjectsList )
                {
                    if( movingObject )
                    {
                        //如果移动方向等于1
                        if( moveDirection == 1 )
                        {
                            //从起点向小路终点移动
                            movingObject.position = Vector3.MoveTowards(movingObject.position, thisTransform.position + laneEnd, moveSpeed.x * Time.deltaTime);
                        
                            //如果到达终点,将游戏物体放到起点
                            if( movingObject.position == thisTransform.position + laneEnd )
                            {
                                movingObject.position = thisTransform.position + laneStart;
                                movingObject.LookAt(thisTransform.position + laneEnd);
                            }
                        }
                        //如果移动方向不等于1
                        else
                        {
                            //从终点向小路起点移动
                            movingObject.position = Vector3.MoveTowards(movingObject.position, thisTransform.position + laneStart, moveSpeed.x * Time.deltaTime);
                        
                            //如果到达起点,将游戏物体放到终点
                            if( movingObject.position == thisTransform.position + laneStart )
                            {
                                movingObject.position = thisTransform.position + laneEnd;
                                movingObject.LookAt(thisTransform.position + laneStart);
                            }
                        }
                    }
                }
            }
        
            /// <summary>
            /// Gizmos下画起始点和结束点
            /// </summary>
            void OnDrawGizmos()
            {
                Gizmos.color = Color.green;
                Gizmos.DrawSphere(transform.position + laneStart, 0.2f);
            
                Gizmos.color = Color.red;
                Gizmos.DrawSphere(transform.position + laneEnd, 0.2f);
            }
        }
    }
    RCGLane
    using UnityEngine;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 加载场景和URL
        /// </summary>
        public class RCGLoadLevel : MonoBehaviour
        {
            /// <summary>
            /// 加载URL
            /// </summary>
            /// <param name="urlName"></param>
            public void LoadURL(string urlName)
            {
                Application.OpenURL(urlName);
            }
        
            /// <summary>
            /// 加载指定场景
            /// </summary>
            /// <param name="levelName"></param>
            public void LoadLevel(string levelName)
            {
                Application.LoadLevel(levelName);
            }
            
            /// <summary>
            /// 重新加载当前场景
            /// </summary>
            public void RestartLevel()
            {
                Application.LoadLevel(Application.loadedLevelName);
            }
        }
    }
    RCGLoadLevel
    using UnityEngine;
    using RoadCrossing.Types;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 玩家
        /// </summary>
        public class RCGPlayer : MonoBehaviour
        {
            /// <summary>
            /// 缓存transform
            /// </summary>
            internal Transform thisTransform;
            /// <summary>
            /// 游戏控制器
            /// </summary>
            internal GameObject gameController;
        
            /// <summary>
            /// 移动速度
            /// </summary>
            public float speed = 0.1f;
            /// <summary>
            /// 是否正在移动
            /// </summary>
            internal bool  isMoving = false;
            /// <summary>
            /// 上一个位置
            /// </summary>
            internal Vector3 previousPosition;
            /// <summary>
            /// 目标位置
            /// </summary>
            internal Vector3 targetPosition;
    
            /// <summary>
            /// 限制玩家移动的物体
            /// </summary>
            public Transform moveLimits;
            
            /// <summary>
            /// 移动动画
            /// </summary>
            public AnimationClip animationMove;
            /// <summary>
            /// 获得金币的动画
            /// </summary>
            public AnimationClip animationCoin;
        
            /// <summary>
            /// 死亡效果的动画列表
            /// </summary>
            public Transform[] deathEffect;
        
            /// <summary>
            /// 从不能移动到能移动的持续时间
            /// </summary>
            public float moveDelay = 0;
        
            /// <summary>
            /// 移动声音
            /// </summary>
            public AudioClip[] soundMove;
            /// <summary>
            /// 获得金币的声音
            /// </summary>
            public AudioClip[] soundCoin;
    
            /// <summary>
            /// AudioSource所属的游戏物体标签
            /// </summary>
            public string soundSourceTag = "GameController";
        
            void Start()
            {
                thisTransform = transform;
    
                targetPosition = thisTransform.position;
            
                gameController = GameObject.FindGameObjectWithTag("GameController");
            }
        
            void Update()
            {
                //让限制玩家移动的物体 跟随玩家移动
                if( moveLimits )
                {
                    Vector3 newPosition = new Vector3();
    
                    newPosition.x = thisTransform.position.x;
    
                    moveLimits.position = newPosition;
                }
    
                //计算移动延迟
                if( moveDelay > 0 )
                    moveDelay -= Time.deltaTime;
            
                //不处于移动状态 移动延迟<=0 时间缩放>0
                if( isMoving == false && moveDelay <= 0 && Time.timeScale > 0 )
                {
                    //垂直抽没有输入值时,才可以左右移动
                    if( Input.GetAxisRaw("Vertical") == 0 )
                    {
                        //向右移动
                        if( Input.GetAxisRaw("Horizontal") > 0 )
                        {
                            Move("right");
                        }
                    
                        //向左移动
                        if( Input.GetAxisRaw("Horizontal") < 0 )
                        {
                            // Move one step to the left
                            Move("left");
                        }
                    }
                
                    //水平轴没有输入值,才可以前后移动
                    if( Input.GetAxisRaw("Horizontal") == 0 )
                    {
                        //向前移动
                        if( Input.GetAxisRaw("Vertical") > 0 )
                        {
                            Move("forward");
                        }
                    
                        //向后移动
                        if( Input.GetAxisRaw("Vertical") < 0 )
                        {
                            Move("backward");
                        }
                    }
                }
                //其余的情况 移动玩家到目标位置
                else
                {
                    //保持向前移动直到 到达目标位置
                    if( thisTransform.position != targetPosition )
                    {
                        //将玩家移动到目标位置
                        thisTransform.position = Vector3.MoveTowards(transform.position, targetPosition, Time.deltaTime * speed);
                    }
                    else
                    {
                        //表示玩家不在移动状态中
                        isMoving = false;
                    }
                }
            }
        
            /// <summary>
            /// 移动
            /// </summary>
            /// <param name="moveDirection">移动方向</param>
            void Move(string moveDirection)
            {
                if( isMoving == false && moveDelay <= 0 )
                {
                    
                    isMoving = true;
                
                    switch( moveDirection.ToLower() )
                    {
                        //向前移动
                        case "forward":
                            //让玩家朝前
                            Vector3 newEulerAngle = new Vector3();
                            newEulerAngle.y = 0;
                            thisTransform.eulerAngles = newEulerAngle;
                    
                            //计算目标位置
                            targetPosition = thisTransform.position + new Vector3(1, 0, 0);
                    
                            //让玩家在固定的网格里移动
                            targetPosition.x = Mathf.Round(targetPosition.x);
                            targetPosition.z = Mathf.Round(targetPosition.z);
                    
                            //记录上一个位置,用来在遇到障碍物的时候,让玩家回到上一个位置
                            previousPosition = thisTransform.position;
                    
                            break;
                    
                        case "backward":
                            //让玩家朝后
                            newEulerAngle = new Vector3();
                            newEulerAngle.y = 180;
                            thisTransform.eulerAngles = newEulerAngle;
    
                            //记录上一个位置,用来在遇到障碍物的时候,让玩家回到上一个位置
                            previousPosition = thisTransform.position;
    
                            //让玩家在固定的网格里移动
                            targetPosition.x = Mathf.Round(targetPosition.x);
                            targetPosition.z = Mathf.Round(targetPosition.z);
    
                            //计算目标位置
                            targetPosition = thisTransform.position + new Vector3(-1, 0, 0);
                    
                            break;
                    
                        case "right":
                            //让玩家朝向右
                            newEulerAngle = new Vector3();
                            newEulerAngle.y = 90;
                            thisTransform.eulerAngles = newEulerAngle;
    
                            //记录上一个位置,用来在遇到障碍物的时候,让玩家回到上一个位置
                            previousPosition = thisTransform.position;
    
                            //让玩家在固定的网格里移动
                            targetPosition.x = Mathf.Round(targetPosition.x);
                            targetPosition.z = Mathf.Round(targetPosition.z);
    
                            //计算目标位置
                            targetPosition = thisTransform.position + new Vector3(0, 0, -1);
                    
                            break;
                    
                        case "left":
                            //让玩家朝向左
                            newEulerAngle = new Vector3();
                            newEulerAngle.y = -90;
                            thisTransform.eulerAngles = newEulerAngle;
    
                            //记录上一个位置,用来在遇到障碍物的时候,让玩家回到上一个位置
                            previousPosition = thisTransform.position;
    
                            //让玩家在固定的网格里移动
                            targetPosition.x = Mathf.Round(targetPosition.x);
                            targetPosition.z = Mathf.Round(targetPosition.z);
    
                            //计算目标位置
                            targetPosition = thisTransform.position + new Vector3(0, 0, 1);
                    
                            break;
                    
                        default:
                            //让玩家朝前
                            newEulerAngle = new Vector3();
                            newEulerAngle.y = 0;
                            thisTransform.eulerAngles = newEulerAngle;
    
                            //计算目标位置
                            targetPosition = thisTransform.position + new Vector3(1, 0, 0);
                            
                            //归一化目标位置
                            targetPosition.Normalize();
    
                            //记录上一个位置,用来在遇到障碍物的时候,让玩家回到上一个位置
                            previousPosition = thisTransform.position;
                    
                            break;
                    }
                
                    //满足条件 播放移动动画
                    if( GetComponent<Animation>() && animationMove )
                    {
                        GetComponent<Animation>().Stop();
                        GetComponent<Animation>().Play(animationMove.name);
                    
                        //基于移动速度设置动画速度
                        GetComponent<Animation>()[animationMove.name].speed = speed;
                    
                        //满足条件播放移动声音
                        if( soundSourceTag != string.Empty && soundMove.Length > 0 )
                            GameObject.FindGameObjectWithTag(soundSourceTag).GetComponent<AudioSource>().PlayOneShot(soundMove[Mathf.FloorToInt(Random.value * soundMove.Length)]);
                    }
                }
            }
        
            /// <summary>
            /// 取消玩家的移动,将玩家弹回到前一个位置
            /// </summary>
            void CancelMove(float moveDelayTime)
            {
                //满足条件播放动画
                if( GetComponent<Animation>() && animationMove )
                {
                    //基于移动速度,倒放动画
                    GetComponent<Animation>()[animationMove.name].speed = -speed;
                }
            
                //将目标位置设置为前一个位置
                targetPosition = previousPosition;
            
                //设置移动延迟
                moveDelay = moveDelayTime;
            }
    
            /// <summary>
            /// 获得金币
            /// </summary>
            void AddCoin(int addValue)
            {
                //调用游戏控制里的改变分数方法
                gameController.SendMessage("ChangeScore", addValue);
            
                //播放获得金币动画
                if( GetComponent<Animation>() && animationCoin && animationMove )
                {
                    GetComponent<Animation>()[animationCoin.name].layer = 1; 
                    GetComponent<Animation>().Play(animationCoin.name); 
                    GetComponent<Animation>()[animationCoin.name].weight = 0.5f;
                }
            
                //播放获得金币声音
                if( soundSourceTag != string.Empty && soundCoin.Length > 0 )
                    GameObject.FindGameObjectWithTag(soundSourceTag).GetComponent<AudioSource>().PlayOneShot(soundCoin[Mathf.FloorToInt(Random.value * soundCoin.Length)]);
            }
        
            /// <summary>
            /// 死亡
            /// </summary>
            /// <param name="deathType">死亡效果类型</param>
            void Die(int deathType)
            {
                //调用游戏控制器的游戏结束方法
                gameController.SendMessage("GameOver", 0.5f);
                
                //创建死亡特效
                if( deathEffect.Length > 0 )
                {
                    Instantiate(deathEffect[deathType], thisTransform.position, thisTransform.rotation);
                }
            
                //销毁游戏物体
                Destroy(gameObject);
            }
        }
    }
    RCGPlayer
    using UnityEngine;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 播放声音
        /// </summary>
        public class RCGPlaySound : MonoBehaviour
        {
            /// <summary>
            /// 声音数组
            /// </summary>
            public AudioClip[] audioList;
        
            /// <summary>
            /// AudioSource所在物体的标签
            /// </summary>
            public string audioSourceTag = "GameController";
            /// <summary>
            /// 游戏开始时是否播放
            /// </summary>
            public bool playOnStart = true;
        
            void Start()
            {
                if( playOnStart == true )
                    PlaySound();
            }
        
            /// <summary>
            /// 播放声音
            /// </summary>
            void PlaySound()
            {
                if( audioSourceTag != string.Empty && audioList.Length > 0 )
                    GameObject.FindGameObjectWithTag(audioSourceTag).GetComponent<AudioSource>().PlayOneShot(audioList[Mathf.FloorToInt(Random.value * audioList.Length)]);
            }
        
            /// <summary>
            /// 根据索引播放声音
            /// </summary>
            void PlaySound(int soundIndex)
            {
                if( audioSourceTag != string.Empty && audioList.Length > 0 ) 
                    GameObject.FindGameObjectWithTag(audioSourceTag).GetComponent<AudioSource>().PlayOneShot(audioList[soundIndex]);
            }
        }
    }
    RCGPlaySound
    using UnityEngine;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 随机化物体的颜色
        /// </summary>
        public class RCGRandomizeColor : MonoBehaviour
        {
            /// <summary>
            /// 颜色数组
            /// </summary>
            public Color[] colorList;
        
            void Start()
            {
                //随机选择一个颜色
                int randomColor = Mathf.FloorToInt(Random.Range(0, colorList.Length));
                //将颜色应用到物体和子物体上
                Component[] comps = GetComponentsInChildren<Renderer>();
                foreach( Renderer part in comps ) 
                    part.GetComponent<Renderer>().material.color = colorList[randomColor];
            }
        }
    }
    RCGRandomizeColor
    using UnityEngine;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 随机化物体的旋转,缩放和颜色
        /// </summary>
        public class RCGRandomizeTransform : MonoBehaviour
        {
            /// <summary>
            /// x轴的旋转范围
            /// </summary>
            public Vector2 rotationRangeX = new Vector2(0, 360);
            /// <summary>
            /// y轴的旋转范围
            /// </summary>
            public Vector2 rotationRangeY = new Vector2(0, 360);
            /// <summary>
            /// z轴的旋转范围
            /// </summary>
            public Vector2 rotationRangeZ = new Vector2(0, 360);
        
            /// <summary>
            /// x轴缩放范围
            /// </summary>
            public Vector2 scaleRangeX = new Vector2(1, 1.3f);
            /// <summary>
            /// y轴缩放范围
            /// </summary>
            public Vector2 scaleRangeY = new Vector2(1, 1.3f);
            /// <summary>
            /// z轴缩放范围
            /// </summary>
            public Vector2 scaleRangeZ = new Vector2(1, 1.3f);
        
            /// <summary>
            /// 是否统一比例缩放
            /// </summary>
            public bool  uniformScale = true;
        
            /// <summary>
            /// 颜色列表
            /// </summary>
            public Color[] colorList;
        
            void Start()
            {
                //随机旋转
                transform.localEulerAngles = new Vector3(Random.Range(rotationRangeX.x, rotationRangeX.y), Random.Range(rotationRangeY.x, rotationRangeY.y), Random.Range(rotationRangeZ.x, rotationRangeZ.y));
    
                //如果是统一缩放,让y,z轴基于x轴的比例缩放
                if( uniformScale == true )
                    scaleRangeY = scaleRangeZ = scaleRangeX;
    
                //随机缩放
                transform.localScale = new Vector3(Random.Range(scaleRangeX.x, scaleRangeX.y), Random.Range(scaleRangeY.x, scaleRangeY.y), Random.Range(scaleRangeZ.x, scaleRangeZ.y));
    
                //随机颜色
                int randomColor = Mathf.FloorToInt(Random.Range(0, colorList.Length));
                Component[] comps = GetComponentsInChildren<Renderer>();
                foreach( Renderer part in comps )
                    part.GetComponent<Renderer>().material.color = colorList[randomColor];
            }
        }
    }
    RCGRandomizeTransform
    using UnityEngine;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 经过一段时间后删除物体,用来在特效播放完成后删除特效
        /// </summary>
        public class RCGRemoveAfter : MonoBehaviour
        {
            //删除物体的等待时间
            public float removeAfter = 1;
        
            void Update()
            {
                removeAfter -= Time.deltaTime;
            
                if( removeAfter <= 0 )
                    Destroy(gameObject);
            }
        }
    }
    RCGRemoveAfter
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    using RoadCrossing.Types;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 商店
        /// </summary>
        public class RCGShop : MonoBehaviour
        {
            /// <summary>
            /// 剩余的金币数量
            /// </summary>
            public int coinsLeft = 0;
            
            /// <summary>
            /// 显示金币的文本
            /// </summary>
            public Transform coinsText;
            
            /// <summary>
            /// 玩家的金币值
            /// </summary>
            public string coinsPlayerPrefs = "Coins";
    
            /// <summary>
            /// 商店道具列表
            /// </summary>
            public ShopItem[] shopItems;
    
            /// <summary>
            /// 当前道具
            /// </summary>
            public int currentItem = 0;
            
            /// <summary>
            /// 存档里的当前玩家键
            /// </summary>
            public string playerPrefsName = "CurrentPlayer";
            
            /// <summary>
            /// 道具的未被选择时的颜色
            /// </summary>
            public Color unselectedColor = new Color(0.6f,0.6f,0.6f,1);
            
            /// <summary>
            /// 道具的选中颜色
            /// </summary>
            public Color selectedColor = new Color(1,1,1,1);
            
            /// <summary>
            /// 暂未使用
            /// </summary>
            public Color errorColor = new Color(1,0,0,1);
    
            void Start()
            {
                //获取剩余金币
                coinsLeft = PlayerPrefs.GetInt(coinsPlayerPrefs, coinsLeft);
                
                //更新金币文本
                coinsText.GetComponent<Text>().text = coinsLeft.ToString();
                
                //获取当前道具
                currentItem = PlayerPrefs.GetInt(playerPrefsName, currentItem);
                
                //更新所有道具
                UpdateItems();
            }
    
            /// <summary>
            /// 更新道具
            /// </summary>
            void UpdateItems()
            {
                for ( int index = 0 ; index < shopItems.Length ; index++ )
                {
                    //从存档中获取这个道具的解锁状态
                    shopItems[index].lockState = PlayerPrefs.GetInt(shopItems[index].playerPrefsName, shopItems[index].lockState);
                    
                    //设置道具的颜色为 未选择的颜色
                    shopItems[index].itemButton.GetComponent<Image>().color = unselectedColor;
                    
                    //如果这个道具已经解锁
                    if ( shopItems[index].lockState > 0 )
                    {
                        //禁用显示价格的物体
                        shopItems[index].itemButton.Find("TextPrice").gameObject.SetActive(false);
                        
                        //高亮当前选择的物体的颜色
                        if ( index == currentItem )    shopItems[index].itemButton.GetComponent<Image>().color = selectedColor;
                    }
                    //如果没有解锁
                    else
                    {
                        //更新这个道具的价格
                        shopItems[index].itemButton.Find("TextPrice").GetComponent<Text>().text = shopItems[index].costToUnlock.ToString();
                    }
                }
            }
    
            /// <summary>
            /// 买道具
            /// </summary>
            /// <param name="itemNumber"></param>
            void BuyItem( int itemNumber )
            {
                //如果这个道具已解锁,选择这个道具
                if ( shopItems[itemNumber].lockState > 0 )
                {
                    SelectItem(itemNumber);
                }
                //如果有足够的金币,消耗金币买这个道具
                else if ( shopItems[itemNumber].costToUnlock <= coinsLeft )
                {
                    //解锁道具
                    shopItems[itemNumber].lockState = 1;
                    
                    //在存档中更新这个道具的状态
                    PlayerPrefs.SetInt(shopItems[itemNumber].playerPrefsName, shopItems[itemNumber].lockState);
                    
                    //扣除金币
                    coinsLeft -= shopItems[itemNumber].costToUnlock;
                    
                    //更新文本
                    coinsText.GetComponent<Text>().text = coinsLeft.ToString();
                    
                    //将剩余金币写入Prefs
                    PlayerPrefs.SetInt(coinsPlayerPrefs, coinsLeft);
                    
                    //选择道具
                    SelectItem(itemNumber);
                }
                
                
                UpdateItems();
            }
            
            /// <summary>
            /// 选择道具
            /// </summary>
            /// <param name="itemNumber"></param>
            void SelectItem( int itemNumber )
            {
                currentItem = itemNumber;
                
                PlayerPrefs.SetInt( playerPrefsName, itemNumber);
            }
        }
    }
    RCGShop
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 显示文本
        /// </summary>
        public class RCGTextByPlatform : MonoBehaviour
        {
    
            /// <summary>
            /// 显示在PC/Mac/Webplayer中的文本
            /// </summary>
            public string computerText = "CLICK TO START";
        
            /// <summary>
            /// 显示在Android/iOS/WinPhone中的文本
            /// </summary>
            public string mobileText = "TAP TO START";
        
            /// <summary>
            /// 显示在Playstation/Xbox/Wii中的文本
            /// </summary>
            public string consoleText = "PRESS 'A' TO START";
        
            void Start()
            {
                #if UNITY_STANDALONE || UNITY_WEBPLAYER
                GetComponent<Text>().text = computerText;
                #endif
            
                #if IPHONE || ANDROID || UNITY_BLACKBERRY || UNITY_WP8 || UNITY_METRO
                GetComponent<Text>().text = mobileText;
                #endif
            
                #if UNITY_WII || UNITY_PS3 || UNITY_XBOX360
                GetComponent<Text>().text = consoleText;
                #endif
            }
        }
    }
    RCGTextByPlatform
    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    namespace RoadCrossing
    {
        /// <summary>
        /// 声音开关
        /// </summary>
        public class RCGToggleSound:MonoBehaviour
        {
            /// <summary>
            /// 播放声音的物体
            /// </summary>
            public Transform soundObject;
        
            /// <summary>
            /// 存档中的名称
            /// </summary>
            public string playerPref = "SoundVolume";
        
            /// <summary>
            /// 声音的当前音量
            /// </summary>
            internal float currentState = 1;
        
            void Awake()
            {
                if( soundObject )
                    currentState = PlayerPrefs.GetFloat(playerPref, soundObject.GetComponent<AudioSource>().volume);
                else   
                    currentState = PlayerPrefs.GetFloat(playerPref, currentState);
            
                SetSound();
            }
        
            /// <summary>
            /// 设置声音大小
            /// </summary>
            void SetSound()
            {
                //设置声音存档
                PlayerPrefs.SetFloat(playerPref, currentState);
    
                Color newColor = GetComponent<Image>().material.color;
    
                //根据声音存档值设置按钮透明度
                if( currentState == 1 )
                    newColor.a = 1;
                else
                    newColor.a = 0.5f;
    
                //应用透明度
                GetComponent<Image>().color = newColor;
    
                //设置音量
                if( soundObject ) 
                    soundObject.GetComponent<AudioSource>().volume = currentState;
            }
        
            /// <summary>
            /// 开关声音
            /// </summary>
            void ToggleSound()
            {
                currentState = 1 - currentState;
            
                SetSound();
            }
        
            /// <summary>
            /// 播放声音
            /// </summary>
            void StartSound()
            {    
                if( soundObject )
                    soundObject.GetComponent<AudioSource>().Play();
            }
        }
    }
    RCGToggleSound

    视频:https://pan.baidu.com/s/1qYPhpsK

    项目:https://pan.baidu.com/s/1mi5C7s0

  • 相关阅读:
    原创frame-relay配置
    iptables详解和练习
    nfs-rpcbind-portmap挂载nfs-network file system
    linux-user-group添加与删除
    cgi-fastcgi-fpm
    lamp介绍
    子签CA以及给别人发CA
    正则表达式
    字符集和字符编码
    C++11新特性
  • 原文地址:https://www.cnblogs.com/revoid/p/6442393.html
Copyright © 2020-2023  润新知