zoukankan      html  css  js  c++  java
  • Unity3D学习笔记(十一):布料和协程

    延迟函数:
    动态资源加载:
    T:Resources.Load<T>(string path);
    Assets - Resources,Resources是一个资源管理的工具类,预制体放在Resources 文件夹下
    绝对路径:从磁盘的根目录开始
    相对路径:相对于Resources文件夹下的路径,用斜杠
    斜杠(除号):Unity,网址http
    反斜杠:Windows资源管理文件夹
    进程:双击一个.exe可执行应用程序,windows就会给我们开启一个进程来运行程序。
    线程:每一个进程中,最少有一个主线程(Main函数是主线程的入口),但是可以有多个辅助线程。
    主线程卡死,程序会崩溃,辅线程卡死,程序不会崩溃,可以把死循环放在辅线程里。
    协程(协同程序):协程是Unity为我们提供的一个模拟多线程的工具,并不是真的多线程。

    开启协程:
    StartCoroutine(string methodName);//由此就开启一个协程,程序会进入到协程里面执行
    StartCoroutine(methodName());//第二种方式
    yield return new WaitForSecond(float time);//等待n秒
    yield return null或0;//等待一帧
    yield return StartCoroutine();//等待此协程执行完毕
    yield break;//直接跳出,结束当前协程

    停止协程:
    StopCoroutines();
    //当使用方法名的字符串形式开启的协程,可以用同样的方式停止协程
    //用方法名加括号开启的协程,只能用StopAllCoroutines停止协程
    StopAllCoroutines();
    协程的返回值是一个迭代器对象,Unity引擎会判断条件是否成立,如果成立再继续执行
    协程也有生命周期,类似update,每一帧Unity都会去判断条件是否成立

    IEnumerator是迭代器
    Current指向第一个元素的指针,MoveNext判断是否可以移到下一个元素

    协程练习:
    1、塔防游戏,5波小怪,没波小怪间隔5秒,每波有20个小怪(间隔1秒生成1个),
    3、有一个按钮(开始游戏),
    3、按照一定的路点移动,从A点移动到B点,走到B点销毁
     
    AsyncOperation异步加载
    YieldInstruction包含所有的异步对象
    1、是否加载完成之后启动场景
    2、加载完成
    3、
    4、加载进度
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class LightOnOff : MonoBehaviour {
        //public int lightOnTime;
        //public int lightOffTime;
        //private Light light;
        public GameObject directionalLight;
        public GameObject[] points;
        private int index = 0;
        // Use this for initialization
        void Start () {
            //思考题
            //地面,灯-点光源(白,红,蓝,绿),依次亮灭
            //light = GetComponent<Light>();
            //InvokeRepeating("LightOn", lightOnTime, 5);
            //InvokeRepeating("LightOff", lightOffTime, 5);
            directionalLight.SetActive(false);
            InvokeRepeating("ChangePointLightState", 1, 1);
        }
        // Update is called once per frame
        void Update () {
                  
           }
        //void LightOn()
        //{
        //    Debug.Log("LightOn");
        //    light.range = 10;
        //}
        //void LightOff()
        //{
        //    Debug.Log("LightOff");
        //    light.range = 0;
        //}
        void ChangePointLightState()
        {
            for (int i = 0; i < points.Length; i++)
            {
                if (i == index)
                {
                    points[i].SetActive(true);
                }
                else
                {
                    points[i].SetActive(false);
                }
            }
            index++;
            index %= points.Length;//防止数组越界
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class AttackMonster : MonoBehaviour {
        private int hp = 100;
           // Use this for initialization
           void Start () {
            InvokeRepeating("MonsterUnderAttack", 1, 1);
        }
           
           // Update is called once per frame
           void Update ()
        {
                  if (Input.GetMouseButton(0))
            {
                CancelInvoke();
                Debug.Log("你取消了进攻");
            }
        }
        void MonsterUnderAttack()
        {
            hp -= 10;
            Debug.Log("怪兽被攻击" + hp);      
            if (hp <= 0)
            {
                CancelInvoke();
                Debug.Log("怪兽被打死了");
            }
         
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class TimeWait : MonoBehaviour {
           // Use this for initialization
           void Start () {
            StartCoroutine(DelayTime());
            Debug.Log("等待两秒");
        }
           
           // Update is called once per frame
           void Update () {
        }
        IEnumerator DelayTime()
        {    
            yield return new WaitForSeconds(2f);
            Debug.Log("两秒到了");
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class ResourcesScript : MonoBehaviour {
           // Use this for initialization
           void Start () {
            //动态资源加载
            GameObject cube = Resources.Load<GameObject>("Prefabs/Cube");
            Instantiate(cube);
            //加载多个资源
            //Resources.LoadAll<GameObject>();
            //异步资源加载
            //异步场景切换
        }
        // Update is called once per frame
        void Update () {
                  
           }
    }
    using System.Collections;
    using System.Collections.Generic;
    using System.Threading;
    using UnityEngine;
    public class LessonTest : MonoBehaviour {
           // Use this for initialization
           void Start () {
            //开启线程
            Thread lxmThread = new Thread(Hello);
            //开启协程,方法名的字符串形式
            StartCoroutine("HelloWorld");//程序从此进入,遇到yield return关键词又从此跳出
            Debug.Log("this is start");
            //开启协程,方法名加括号形式
            //StartCoroutine(HelloWorld());
            //停止协程,方法名的字符串形式,被挂起的程序不会执行
            StopCoroutine("HelloWorld");
            //停止所有协程
            StopAllCoroutines();
            //停止协程,不能用方法名加括号形式
            //用方法名加括号开启协程,只能用StopAllCoroutines关闭
            //StopCoroutine(HelloWorld());
        }
        // Update is called once per frame
        void Update () {
                  
           }
        void Hello()
        {
        }
        IEnumerator HelloWorld()
        {
            //StopAllCoroutines();//"this is before HelloWorld"仍会执行
            Debug.Log("this is before HelloWorld");//程序执行到此包括之前,和执行一个普通的方法没有任何区别
            yield return new WaitForSeconds(2);//直到遇到yield return关键字,程序会跳出,从哪来跳哪去(程序被挂起2秒之后再执行)
            Debug.Log("this is after HelloWorld");//如果迭代器对象满足条件了,程序就会再次从此处执行。
            yield return new WaitForSeconds(2);//程序从Unity引擎进入,并跳回Unity引擎,不会跳到主线程的StartCoroutine
            Debug.Log("this is last HelloWorld");
            //等最后一帧判断
            //yield return new WaitForEndOfFrame();
            //等待一帧,可以开启另一个update
            //yield return null;
            //while (true)//模拟update,卡死模拟线程,
            //{
            //    yield return null;//程序从此跳出,等一帧再进来
            //}
            //协程的嵌套
            yield return StartCoroutine("ThankYou");
            Debug.Log("this is second last HelloWorld");
            //等待物理帧更新
            yield return new WaitForFixedUpdate();
            //等待百度响应
            yield return new WWW("www.baidu.com");
            //WWW的资源热更新
        }
        IEnumerator ThankYou()
        {
            Debug.Log("this is before ThankYou");
            yield return new WaitForSeconds(2);
            Debug.Log("this is after ThankYou");
        }
     
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    using UnityEngine.UI;
    public class GUITest : MonoBehaviour {
        public Slider slider;
        public Texture image;
        public float height;
        public float width;
        public float addHeight;
        public float uiNormalFactor = 4;//血条缩放因子的系数,控制血条缩放大小
        private float totelHealth;
        private Transform player;
        private Camera camera;
        private float uiScaleFactor = 1;//血条缩放因子
        private float _progress;//真实进度
        private float m_progress;//虚拟进度
        // Use this for initialization
        void Start () {
            player = GameObject.Find("CJY").transform;
            camera = Camera.main;
            totelHealth = width;
        }
           
           // Update is called once per frame
           void Update () {
            //减血,血条左边框位置固定的,从右边减血条宽度
            if (Input.GetKeyDown(KeyCode.Space))
            {
                width -= totelHealth * 0.1f;//减剩余血量的百分之十
                if (width <= 0)
                {
                    Dead();
                }
            }
        }
        private void Dead()
        {
            Destroy(gameObject);
        }
        void OnGUI()
        {
            //OnGUI在商业中只负责调试工具,实际开发用UGUI
            //Rect类似屏幕坐标系坐标,x指的是UI左上角离屏幕左边框的距离
            //绘制血条
            //位置:屏幕坐标转世界转世界坐标
            //Vector3 screenPosl = camera.W
            Vector3 targetPos = new Vector3(player.position.x, player.position.y + addHeight, player.position.z);
            Vector3 screenPos = camera.WorldToScreenPoint(targetPos);
            uiScaleFactor = 1 / screenPos.z * uiNormalFactor;//血条缩放因子,血条近大远小,z分量去调节
            //屏幕坐标转世界坐标系,无论在摄像机前后,都换算出一个坐标
            //用点乘,判断摄像机前后位置,在后面不绘制
            Vector3 cameraForward = camera.transform.forward;
            Vector3 camera2Player = transform.position - camera.transform.position;
            if (Vector3.Dot(cameraForward, camera2Player) > 0)
            {
                GUI.DrawTexture(new Rect(screenPos.x - width / 2 * uiScaleFactor,
                    Screen.height - screenPos.y - height / 2 * uiScaleFactor,
                    width * uiScaleFactor,
                    height * uiScaleFactor),
                    image);
            }
            //场景切换
            //1、场景打包,Build Setting 加入场景
            //2、引用命名空间,using UnityEngine.SceneManagement;
            //异步切换场景,场景大,加载慢,用SceneManager只有加载完毕,才会显示场景
            if (GUI.Button(new Rect(Screen.width / 2 - width / 2, Screen.height / 2 - height / 2, width, height), "开始游戏"))
            {
                AsyncOperation oepration = SceneManager.LoadSceneAsync("GameScene");
                StartCoroutine(LoadSceneAsync(oepration));        //在协程里加载
            }
            GUILayout.Label("加载进度: " + m_progress);//把加载进度显示在屏幕右上角
            slider.value = m_progress;//把加载进度赋值给滚动条
        }
        IEnumerator LoadSceneAsync(AsyncOperation oepration)
        {
            oepration.allowSceneActivation = false;//自动加载场景关闭,改为手动切换
            while (m_progress < 1.0)
            {
                if (_progress < 0.9f)//小于0.9f时,让虚拟进度追赶真实进度,真实进度会卡在0.9f自动加载场景处
                {
                    _progress = oepration.progress;
                    m_progress = Mathf.MoveTowards(m_progress, _progress, 0.01f);//显示虚拟进度,,速度0.01f
                }
                else//大于等于0.9f时,让虚拟进度超过真实进度,改为追赶1.0
                {
                    m_progress = Mathf.MoveTowards(m_progress, 1.0f, 0.01f);
                }
                yield return 0;//等待1帧
            }
            yield return new WaitForSeconds(1);//等待1秒再做切换
            oepration.allowSceneActivation = true;
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class FindPath : MonoBehaviour {
        public Transform[] paths;
        public Vector3 dir;
        public float moveSpeed = 0.1f;
        public float rotSpeed = 5;
        int index = 0;
        // Use this for initialization
        void Start () {
                  
           }
           
           // Update is called once per frame
           void Update () {
            if (Vector3.Distance(paths[index].position, transform.position) <= 0.5f)
            {
                if (index == 4)
                {
                    Destroy(gameObject);
                }
                index++;
                index %= paths.Length;
            }
            else
            {
                dir = paths[index].position - transform.position;
                Quaternion targetRotation = Quaternion.LookRotation(dir);
                transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 1 / Quaternion.Angle(transform.rotation, targetRotation) * rotSpeed);
                transform.position = Vector3.Lerp(transform.position, paths[index].position, 1 / Vector3.Distance(transform.position, paths[index].position) * moveSpeed);               
            }
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class EnemySpawn : MonoBehaviour {
        public float monsterRate = 1f;
        private int monsterNum;
        // Use this for initialization
        void Start () {
           
        }
           
           // Update is called once per frame
           void Update () {
          
        }
        IEnumerator EnemyTeamBirth()
        {
            InvokeRepeating("EnemyBirth", 1, monsterRate);
            yield return new WaitForSeconds(25);
            InvokeRepeating("EnemyBirth", 1, monsterRate);
            yield return new WaitForSeconds(25);
            InvokeRepeating("EnemyBirth", 1, monsterRate);
            yield return new WaitForSeconds(25);
            InvokeRepeating("EnemyBirth", 1, monsterRate);
            yield return new WaitForSeconds(25);
            InvokeRepeating("EnemyBirth", 1, monsterRate);
        }
        void EnemyBirth()
        {
            monsterNum++;
            GameObject cube = Resources.Load<GameObject>("Prefabs/Cube");
            Instantiate(cube);
            Debug.Log(monsterNum);
            if (monsterNum >= 20)
            {
                CancelInvoke();
                monsterNum = 0;
            }
           
        }
        void OnGUI()
        {
            if (GUI.Button(new Rect(1, 1, 100, 20), "开始游戏"))
            {
                StartCoroutine("EnemyTeamBirth");
            }
        }
    }

    复习

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class w07d3 : MonoBehaviour
    {
        Rigidbody rig;
        public float force = 10;
        public float radius = 5;
        void Start()
        {
            //rig = GetComponent<Rigidbody>();
            //rig.AddForce(transform.up * force, ForceMode.Impulse);
            /*                       Ft = mv
               Force = 0,    持续力   F = ma
               //
               // 摘要:
               //     ///
               //     Add an instant force impulse to the rigidbody, using its mass.
               //     ///
               Impulse = 1,         t = 1,  F = mv
               //
               // 摘要:
               //     ///
               //     Add an instant velocity change to the rigidbody, ignoring its mass.
               //     ///
               VelocityChange = 2,   t = m = 1,  F = v
               //
               // 摘要:
               //     ///
               //     Add a continuous acceleration to the rigidbody, ignoring its mass.
               //     ///
               Acceleration = 5      m = 1   F = v/t = a
               */
            // 射线检测:必须要有碰撞器组件
            // 相交球
            //Collider[] cols = Physics.OverlapSphere(transform.position, radius, LayerMask.GetMask("Enemy", "Boss"));
            //foreach (var item in cols)
            //{
            //    Debug.Log(item.transform.name);
            //}
            // 开始按钮
            // 5波小怪  每波之间间隔5秒
            // 每一波有20个小怪 每个小怪 间隔1秒
        }
        private void OnDrawGizmos()
        {
            Gizmos.color = new Color(0, 1, 0, 0.3f);
            Gizmos.DrawSphere(transform.position, radius);
        }
        void Update1()
        {
            RaycastHit hit;
            Ray ray = new Ray(transform.position, transform.forward);
            if (Physics.Raycast(ray, out hit, 100, LayerMask.GetMask("Enemy", "Boss")))
            {
                Debug.Log("name:" + hit.transform.name);
                // 检测到的游戏物体的位置
                Debug.Log("pos :" + hit.transform.position);
                // 射线与碰撞框相交的点的位置
                Debug.Log("hit pos :" + hit.point);
                //Debug.Log("distance :" + hit.distance);
                Vector3 dir = hit.point - ray.origin;
                float distance = dir.magnitude;
            }
        }
    }
    用栈作对象池存储对象
    list - LinkedListNode,存储节点
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    public class Pool<T> where T : class  // 对泛型做限制
        // 限制为 引用类型 where T : class
        // 限制为 值类型   where T : struct
        // 限制T有默认无参构造函数 where T : new()
        // 限制T为某类型的子类    where T : UnityEngine.Object
        // 限制T 继承了某接口     where T : IEnumerable
        // 组合使用 通过逗号分割   组合的时候 new()写在末尾
    {
        Stack<T> pool = new Stack<T>();
        Stack<int> pool = new Stack<int>();  // 栈 先进后出
        Queue<int> queue = new Queue<int>();  // 队列 先进先出
        LinkedList<int> link = new LinkedList<int>();
        void Start()
        {
            #region 栈操作
            pool.Push(10);
            pool.Push(5);               // 入栈
            int result = pool.Pop();    // 弹栈
            //result = pool.Pop();
            result = pool.Peek();       // 访问栈顶元素 该元素没有弹栈
            Debug.Log(result);
            Debug.Log(pool.Count);
            #endregion
            #region 队列操作
            queue.Enqueue(10);             // 入队
            queue.Enqueue(5);
            int result = queue.Dequeue();  // 出队  元素会从队列里移除
            result = queue.Peek();         // 访问队头的元素 该元素没有出队
            Debug.Log(result);
            Debug.Log(queue.Count);
            #endregion
            #region 链表操作
            link.AddLast(10);
            link.AddLast(9);
            link.AddFirst(11);
            #endregion
        }
        public void Push(T item)
        {
            pool.Push(item);
        }
        public T Pop()
        {
            if (pool.Count == 0)
            {
                return default(T);      // 使用类型的默认值 如果T是引用类型 返回null
            }
            return pool.Pop();
        }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    // 管理所有的对象池 对于各个类型 都需要有相应的方法
    public class PoolManager : MonoBehaviour {
        enum EPoolType
        {
            Bullet,
            Enemy,
        }
        Dictionary<EPoolType, Pool<GameObject>> pools = new Dictionary<EPoolType, Pool<GameObject>>();
        public GameObject bulletPrefab;
        public Texture t;
        //Pool<GameObject> bulletPool = new Pool<GameObject>();
        //Pool<GameObject> enemyPool = new Pool<GameObject>();
        private void Awake()
        {
            bulletPrefab = Resources.Load<GameObject>("Bullets/Bullet"); //Resources.Load("Bullet") as GameObject;
            t = Resources.Load<Texture>("Effects/Light");
        }
        void Start () {
            // 对于对象池做初始化操作
            pools.Add(EPoolType.Bullet, new Pool<GameObject>());
            pools.Add(EPoolType.Enemy, new Pool<GameObject>());
           }
           
           void Update () {
                  
           }
        public GameObject SpawnBullet(Vector3 pos, Quaternion q)
        {
            GameObject bullet = pools[EPoolType.Bullet].Pop();
            //GameObject bullet = bulletPool.Pop();
            if(bullet == null)
            {
                bullet = Instantiate(bulletPrefab, pos, q);
            }
            else
            {
                bullet.SetActive(true);
            }
            return bullet;
        }
        public void PushBullet(GameObject bullet)
        {
            bullet.SetActive(false);
            //bulletPool.Push(bullet);
            pools[EPoolType.Bullet].Push(bullet);
        }
    }
  • 相关阅读:
    JavaScript 执行机制
    前端问题总结
    【2020 -02- 07】组件与模板
    【2020-02-07】组件与模板
    【2020-01-23】组件与模板 -- 模板语法
    关于java.lang.UnsatisfiedLinkError的处理
    两个Activity传递数据和对象
    Android Activity为什么要细化出onCreate、onStart、onResume、onPause、onStop、onDesdroy这么多方法让应用去重载?(转)
    通过Android Studio 导出Jar包
    关于AccessibilityService的用法(转)
  • 原文地址:https://www.cnblogs.com/vuciao/p/10362917.html
Copyright © 2011-2022 走看看