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判断是否可以移到下一个元素
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 = ;
// Use this for initialization
void Start () {
//思考题
//地面,灯-点光源(白,红,蓝,绿),依次亮灭
//light = GetComponent<Light>();
//InvokeRepeating("LightOn", lightOnTime, 5);
//InvokeRepeating("LightOff", lightOffTime, 5);
directionalLight.SetActive(false);
InvokeRepeating("ChangePointLightState", , );
}
// 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 = ; 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 = ;
// Use this for initialization
void Start () {
InvokeRepeating("MonsterUnderAttack", , );
} // Update is called once per frame
void Update ()
{
if (Input.GetMouseButton())
{
CancelInvoke();
Debug.Log("你取消了进攻");
}
}
void MonsterUnderAttack()
{
hp -= ;
Debug.Log("怪兽被攻击" + hp);
if (hp <= )
{
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();//直到遇到yield return关键字,程序会跳出,从哪来跳哪去(程序被挂起2秒之后再执行)
Debug.Log("this is after HelloWorld");//如果迭代器对象满足条件了,程序就会再次从此处执行。
yield return new WaitForSeconds();//程序从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();
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 = ;//血条缩放因子的系数,控制血条缩放大小
private float totelHealth;
private Transform player;
private Camera camera;
private float uiScaleFactor = ;//血条缩放因子
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 <= )
{
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 = / screenPos.z * uiNormalFactor;//血条缩放因子,血条近大远小,z分量去调节
//屏幕坐标转世界坐标系,无论在摄像机前后,都换算出一个坐标
//用点乘,判断摄像机前后位置,在后面不绘制
Vector3 cameraForward = camera.transform.forward;
Vector3 camera2Player = transform.position - camera.transform.position;
if (Vector3.Dot(cameraForward, camera2Player) > )
{
GUI.DrawTexture(new Rect(screenPos.x - width / * uiScaleFactor,
Screen.height - screenPos.y - height / * uiScaleFactor,
width * uiScaleFactor,
height * uiScaleFactor),
image);
}
//场景切换
//1、场景打包,Build Setting 加入场景
//2、引用命名空间,using UnityEngine.SceneManagement;
//异步切换场景,场景大,加载慢,用SceneManager只有加载完毕,才会显示场景
if (GUI.Button(new Rect(Screen.width / - width / , Screen.height / - height / , 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 ;//等待1帧
}
yield return new WaitForSeconds();//等待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 = ;
int index = ;
// 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 == )
{
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, / Quaternion.Angle(transform.rotation, targetRotation) * rotSpeed);
transform.position = Vector3.Lerp(transform.position, paths[index].position, / 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", , monsterRate);
yield return new WaitForSeconds();
InvokeRepeating("EnemyBirth", , monsterRate);
yield return new WaitForSeconds();
InvokeRepeating("EnemyBirth", , monsterRate);
yield return new WaitForSeconds();
InvokeRepeating("EnemyBirth", , monsterRate);
yield return new WaitForSeconds();
InvokeRepeating("EnemyBirth", , monsterRate);
}
void EnemyBirth()
{
monsterNum++;
GameObject cube = Resources.Load<GameObject>("Prefabs/Cube");
Instantiate(cube);
Debug.Log(monsterNum);
if (monsterNum >= )
{
CancelInvoke();
monsterNum = ;
} }
void OnGUI()
{
if (GUI.Button(new Rect(, , , ), "开始游戏"))
{
StartCoroutine("EnemyTeamBirth");
}
}
}
复习
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class w07d3 : MonoBehaviour
{
Rigidbody rig;
public float force = ;
public float radius = ;
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.3f);
Gizmos.DrawSphere(transform.position, radius);
}
void Update1()
{
RaycastHit hit;
Ray ray = new Ray(transform.position, transform.forward);
if (Physics.Raycast(ray, out hit, , 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;
}
}
}
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();
pool.Push(); // 入栈
int result = pool.Pop(); // 弹栈
//result = pool.Pop();
result = pool.Peek(); // 访问栈顶元素 该元素没有弹栈
Debug.Log(result);
Debug.Log(pool.Count);
#endregion
#region 队列操作
queue.Enqueue(); // 入队
queue.Enqueue();
int result = queue.Dequeue(); // 出队 元素会从队列里移除
result = queue.Peek(); // 访问队头的元素 该元素没有出队
Debug.Log(result);
Debug.Log(queue.Count);
#endregion
#region 链表操作
link.AddLast();
link.AddLast();
link.AddFirst();
#endregion
}
public void Push(T item)
{
pool.Push(item);
}
public T Pop()
{
if (pool.Count == )
{
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);
}
}
Unity3D学习笔记(十一):布料和协程的更多相关文章
- Swoft2.x 小白学习笔记 (三) --- Task、协程
介绍swoft中 1.Task 2.协程 一:Task任务: 1.配置,在 app/bean.php文件中加入 'httpServer' => [ // ... 'on' => [ Swo ...
- python3.4学习笔记(十一) 列表、数组实例
python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...
- Go语言学习笔记十一: 切片(slice)
Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...
- unity3d学习笔记(一) 第一人称视角实现和倒计时实现
unity3d学习笔记(一) 第一人称视角实现和倒计时实现 1. 第一人称视角 (1)让mainCamera和player(视角对象)同步在一起 因为我们的player是生成的,所以不能把mainCa ...
- Unity3D学习笔记2——绘制一个带纹理的面
目录 1. 概述 2. 详论 2.1. 网格(Mesh) 2.1.1. 顶点 2.1.2. 顶点索引 2.2. 材质(Material) 2.2.1. 创建材质 2.2.2. 使用材质 2.3. 光照 ...
- Unity3D学习笔记3——Unity Shader的初步使用
目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. 渲染 ...
- Unity3D学习笔记4——创建Mesh高级接口
目录 1. 概述 2. 详论 3. 其他 4. 参考 1. 概述 在文章Unity3D学习笔记2--绘制一个带纹理的面中使用代码的方式创建了一个Mesh,不过这套接口在Unity中被称为简单接口.与其 ...
- Unity3D学习笔记6——GPU实例化(1)
目录 1. 概述 2. 详论 3. 参考 1. 概述 在之前的文章中说到,一种材质对应一次绘制调用的指令.即使是这种情况,两个三维物体使用同一种材质,但它们使用的材质参数不一样,那么最终仍然会造成两次 ...
- Unity3D学习笔记7——GPU实例化(2)
目录 1. 概述 2. 详论 2.1. 实现 2.2. 解析 3. 参考 1. 概述 在上一篇文章<Unity3D学习笔记6--GPU实例化(1)>详细介绍了Unity3d中GPU实例化的 ...
- Unity3D学习笔记8——GPU实例化(3)
目录 1. 概述 2. 详论 2.1. 自动实例化 2.2. MaterialPropertyBlock 3. 参考 1. 概述 在前两篇文章<Unity3D学习笔记6--GPU实例化(1)&g ...
随机推荐
- 第五课 JAVA反射获取对象属性和方法(通过配置文件)
Service1.java package reflection; public class Service1 { public void doService1(){ System.out.print ...
- mysql transaction 事务
1.事务简介 一个"最小的"不可再分的"工作单元". 一个事务通常对应了一个完整的业务.如:银行的转账功能,a转账给b,a扣钱,b加钱. 一个事务包含一条或多条 ...
- Sql Server 2016 Always On集群搭建
第一步,配置好windows环境 第二步 (配置内容较多--需单写) 需要做windows集群 安装WSFC集群组件 直接在Windows服务器管理工具中,增加功能模块,集群故障转移模块 并增加节点 ...
- HTML状态消息
HTTP 状态消息 当浏览器从 web 服务器请求服务时,可能会发生错误. 以下列举了有可能会返回的一系列 HTTP 状态消息: 1xx: 信息 消息: 描述: 100 Continue 服务器仅接收 ...
- 高性能mysql 4 ,5章
第4章 1:查询优化,多表连接时只取需要的列,要对select * 保持怀疑. 2:如果发现访问的数据行数很大,而生成的结果中数据行很少,那么可以尝试更复杂的修改 a: 使用覆盖索引,b: 更改架构, ...
- oj2892(字典树)
一改时间以后WA了,我就知道这题是考字典树,可惜代码怎么也不会敲了,郁闷. #include <stdio.h>#include <string.h>#include < ...
- PAT 1034 Head of a Gang[难][dfs]
1034 Head of a Gang (30)(30 分) One way that the police finds the head of a gang is to check people's ...
- webdriver鼠标上下滑动
有时候我们需要对窗口显示的页面上下滑动,以显示当前正在处理的位置,这就需要用到webdriver模拟鼠标上下滑动 package test20161201; import org.openqa.sel ...
- AOAPC I: Beginning Algorithm Contests (Rujia Liu) Volume 6. Mathematical Concepts and Methods
uva 106 这题说的是 说计算 x^2 + y^2 = z^2 xyz 互质 然后计算个数和 在 N内 不在 勾股数之内的数的个数 然后去找需要的 维基百科上 看到 另 n*m*2 =b ...
- Python 为什么sys.stdout.write 输出时后面总跟一个数字
sys.stdout 是标准输出文件.write就是往这个文件写数据. 合起来就是打印数据到标准输出 因为-在交互模式下会输出函数返回值,而write会返回输出的字符数量.在命令行里不会显示