Unity脚本支持的语言:
3.x 4.x 5.x:C#、JavaScript、BOO、C与C++ 等。
Unity2017以后:C#
修改Unity范本:
路径:安装目录\Editor\Data\Resources\ScriptTemplates
修改范本:81-C# Script-NewBehaviourScript.cs.txt
怎么引用Unity中的类?
创建自己的Debugl类:
创建平台:选类库
框架选:3.5(重选框架:项目=》最下面属性=》选择框架)
引入所有类库:E:\Unity2018.4.8f1\Editor\Data\Managed\UnityEngine
直接复制类库到自己工程目录下面
开发工具:
MonoDevelop:MonoDevelop 是个适用于 Linux、Mac OS X 和 Microsoft Windows 的开放源代码集成开发环境,主要用来开发 Mono 与 .NET Framework 软件。
VS2019:
设置VS2019为开发工具:
debug类
Debug.Log("控制台输出 信息");
Debug.LogWarning("控制台输出 警告 信息");
Debug.LogError("控制台输出 错误 信息");
Debug.Log与Print区别?
Print:print 是MonoBehaviour的一个成员。print 必须要继承 MonoBehaviour 类,
Debug.Log:Debug则是一个独立的、密闭的类。Debug不需要继承 MonoBehaviour 类,
Application类:
1.使用宏定义和Application.platform判断运行平台
//Android平台
#if UNITY_ANDROID
debug.log("Android");
#endif
//苹果平台
#if UNITY_IPHONE
debug.log("IOS");
#endif
//Windows平台
#if UNITY_STANDALONE_WIN
Debug.Log("Windows");
#endif
2.Application.platform判断平台:
if (Application.platform == RuntimePlatform.Android)
{
Debug.Log("Android");
}else if(Application.platform == RuntimePlatform.IPhonePlayer)
{
Debug.Log("IOS");
}
else if (Application.platform == RuntimePlatform.WindowsEditor)
{
Debug.Log("Window");
}
SceneManager类
跳转场景的方法
//当前跳转场景方法
SceneManager.LoadScene(1);//场景序号
SceneManager.LoadScene("Scene2");//场景名称
MonoBehaviour类
MonoBehaviour类:是一个基类,所有 Unity 脚本都派生自该类
作用
让脚本可以像组件一样挂在物体上。
包含脚本生命周期:
Awake()函数是加载场景时运行,就是说在游戏开始之前初始化变量或游戏状态。
OnEnable():当对象变为可用或激活状态时被调用
Start()函数是在第一次启动时执行,用于游戏对象的初始化,在Awake()函数之后。
FixedUpdate()与Update()函数相似,但是每个固定物理时间间隔调用一次,用于物理状态的更新。
Update()是在运行时每一帧必执行的函数,用于更新游戏场景和状态。
LateUpdate()是在Update()函数执行后再次被执行。
OnGUI():渲染和处理OnGUI事件
OnDisable():当前对象不可用或非激活状态时被调用
OnDestroy():当前对象被销毁时调用
详细脚本生命周期看下图:
Collision事件
OnCollisionEnter函数:当碰撞体或者刚体与其他碰撞体或者刚体开始接触时调用
OnCollisionStay函数:当碰撞体或者刚体与其他碰撞体或者刚体保持接触时调用
OnCollisionExit函数:当碰撞体或者刚体与其他碰撞体或者刚体停止接触时调用
Trigger事件
OnTriggerEnter函数:当其他碰撞体进入触发器时调用
OnTriggerStay函数:当其他碰撞体停留触发器时调用
OnTriggerExit函数:当其他碰撞体离开触发器时调用
GameObject类
GameObject类继承于Object类,是Unity场景里面所有实体的基类。
1.物体状态:
Debug.Log(obj.activeSelf); //显示物体激活状态(只读)
obj.SetActive(true);//设置物体的激活状态
SetActive显示/隐藏游戏对象:在Unity中,要激活游戏对象的方法就是使用SetActive(),就是说通过此方法让游 戏对象显示或者隐藏。
2.名字、标签、层:
Debug.Log(obj.name); //输出物体名字
Debug.Log(obj.tag);//输出标签
Debug.Log(obj.layer);//输出层(删除数字)
3.查找方法:
通过对象名称(Find方法)GameObject.Find
通过标签获取单个游戏对象(FindWithTag方法)
通过标签获取多个游戏对象(FindGameObjectsWithTags方法)
//Find只能查找激活的物体
obj3=GameObject.Find("Cube");
//通过标签查找物体
obj3=GameOject.FindGameObjectWithTag("MainCamera");
//通过标签获取多个游戏对象
objs=GameOject.FindGameObjectWithTag("MainCamera");
物体:
CreatPrimitive方法是创建一个原生几何体,也就是带有基本网格渲染器和相应碰撞器的游戏对象。
例如:Cube、Sphere、Capsule等。
GameObject.CreatePrimitive(PrimitiveType.Cube);
Instantiate实例化:Unity提供克隆游戏对象的方法
Instantiate(GameObject);
Instantiate(GameObject, position, rotation);
//创建基础物体
GameObject.CreatePrimitive(PrimitiveType.Cube);
//实例化基础物体,实例化物体后面带(Clone)
GameObect obj9=(GameObject) Instantiate(obj3);
//obj.name="obj3";
//创建空物体
GameObject obj1=new GameObject("NullObject");
Destory销毁:Destory()是主要用于销毁游戏对象以及组件,但不会再引用那个被销毁的对象
Destroy(GameObject);
Destroy(GameObject, time);
组件:
GetComponent获取组件:访问游戏对象的组件的方法
GameObject.GetComponent<type>()
增加组件:AddComponent
gameObject.AddComponent("SphereCollider") as SphereCollider;
销毁组件:
Destroy(cube.GetComponent<Rigidbody>());
状态:enable
创建墙壁
Input类
Input类是输入系统的接口。使用这个类能够读取输入管理器 设置的按键,以及访问移动设备的多点触控或加速感应数据。
鼠标:
KeyCode键值
Input.GetMouseButton(0)
Input.GetMouseButtonDown(0)
Input.GetMouseButtonUp(0)
键盘:
Input.GetKey(+键值)
Input.GetKeyDown(+键值)
Input.GetKeyUp(+键值)
虚拟轴
键盘
Input.GetAxis("Horizontal")
Input.GetAxis("Vertical")
鼠标
Input.GetAxis("Mouse X")
Input.GetAxis("Mouse Y")
Input.GetAxis("Mouse ScrollWheel")
InputManager简介
Unity提供了自定义按键的功能,使用时需要在输入管理器中配置自定义按键,首先在Unity导航菜单栏中选中“Editor”->“Project Setting”->“Input”菜单项,打开输入管理器界面,然后进行修改自定义按键即可。
按键检测
Input.anyKey:按键按住时为true
Input.anyKeyDown:按键按下时为ture
鼠标位置
mousePosition鼠标当前的像素坐标位置。(只读)
Transform类
场景里的每个对象都含有Transform,用来存储并控制物体的位置、旋转和缩放。
作用:
① 负责游戏对象的变换
② 维持父子关系
在Hierarchy面板可以看到,每一个Transform可以有一个父级,允许分层次管理位、旋转和缩放。
父子关系
在Hierarchy视窗中,通过把一个游戏对象拖放到另一个游戏对象之上来创建父物体,这样将创建一个父子关系 来关联这两个游戏对象。
物体间父子关系作用
当一个游戏对象是另一个游戏对象的父物体时,其子游戏对象会随着父游戏对象移动、旋转和缩放。
举个例子来说,你的胳膊(子物体)属于你的身体(父物体),当你旋转身体时,你的胳膊也会跟着旋转一样。
任何物体都可以有多个子物体,但只能有一个父物体。通过构建物体间的父子关,在开发过程中提供了很大方便。
SetParent
设置变换的父级。
位置:
localPosition:相对于父级的变换的位置
Position:在世界坐标系中,transform的位置
eulerAngles:旋转作为欧拉角度
localEulerAngles:相对于父级的变换的旋转欧拉角度
rotation :在世界坐标系中物体变换的旋转角度作为Quaternion储存
localRotation:相对于父级的旋转
移动:
沿着物体本身坐标轴
沿着世界坐标轴
Translate
根据 translation 的方向和距离移动变换
transform.position:指定物体在世界坐标下的位置。
transform.Translate:指物体相对位移的单位。
transform.Rotate:指物体旋转。
transform.eulerAngles:指物体的角度。
transform.localScale:指物体的缩放,注意的是缩放各个轴不能为0,否则会消失
Find
可以查找隐藏子物体
GetChild:
按索引返回变换子项
0开头
LookAt:
旋转变换,使向前矢量指向 target 的当前位置
始终是Z轴看向目标点
Rigidbody类
可使游戏对象在物理系统的控制下来运动。
AddForce:此方法被调用时,会施加给刚体一个瞬时力。在力的作用下,会产生一个加速度进行运动。
AddTorque:此方法被调用时,会给刚体添加一个扭矩。
Sleep:此方法可使刚体进入休眠状态,且至少休眠一帧,一般在Awake()函数里面。
WakeUp:此方法使刚体从休眠状态唤醒。
Time类
Time类是在Unity中获取时间信息的接口类,可以用来计算时间的消耗,只有静态属性。
Time.time:当前游戏已经运行的时间
Time.deltaTime:上一帧消耗的时间;
timeScale:时间流逝的缩放。可用于慢动作效果。
Mathf类
Mathf是Unity提供的所有数学计算时需要用到的函数
Mathf.Abs()------取绝对值
Mathf.Ceil()------向上取整,返回值为Float类型
Mathf.CeilToInt()------向上取整,返回值为Int类型
Mathf.Floor()--------向下取整,返回值为Float类型
Mathf.FloorToInt()--------向下取整,返回值为Int类型
Mathf.Round()--------四舍五入,返回值为Float类型
Mathf.RoundToInt()--------四舍五入,返回值为Int类型
Mathf.Pow(float x,float y)--------返回x的y次方
Mathf.Sqrt(float x)-----------返回x的平方根
Mathf.DeltaAngle(float current,float target)---------返回两个角夹角的最小值
Mathf.ClosestPowerOfTwo(float x)------------返回2的x次方
Mathf.Clamp
Mathf.Clamp(float current,float min,float max)
限制 current的值在min,max之间,如果current大于max,则返回max,如果current小于min,则返回min,否者返回current;
Mathf.Lerp(float a, float b, float t)--------线性插值,t为一个比例,范围[0,1]
t=0的时候返回a,t=1的时候返回b,t=0.5时返回(a+b)/2 先快后慢
Mathf.MoveTowards(float current, float target, float maxDelta)------与Mathf.Lerp本质上是一样的 匀速
如果maxDelta为负数,current的值将远离target
Mathf.PingPong(float t,float length)----返回值在0和length之间
Random类
用于产生随机数。
Random.Range第二个数为
整数: 第二个数取不到
小数: 第二个数能取到
Application类
Coroutine协同
在主线程运行的同时开启另一段逻辑处理,来协助当前程序的执行
协程不是多线程,Unity的协程是在每帧结束之后去检测yield的条件是否满足
Unity3D是否支持写成多线程程序?如果支持的话需要注意什么?
仅能从主线程中访问Unity3D的组件,对象和Unity3D系统调用
支持:如果同时你要处理很多事情或者与Unity的对象互动可以用thread,否则使用coroutine。
注意:C#中有lock这个关键字,以确保只有一个线程可以在特定时间内访问特定的对象
例子
StartCoroutine("MyFun");//调用协程
StopCoroutine("MyFun");//终止协程
StopAllCoroutines();//终止所有协程
IEnumerator MyFun()
{
Debug.Log("协同被调用1");
yield return null;
Debug.Log("协同被调用2");
}
Vector类
简写
up =Vector3(0, 1, 0)
down 用于编写 Vector3(0, -1, 0) 的简便方法。
left 用于编写 Vector3(-1, 0, 0) 的简便方法。
right 用于编写 Vector3(1, 0, 0) 的简便方法。
forward 用于编写 Vector3(0, 0, 1) 的简便方法。
back 用于编写 Vector3(0, 0, -1) 的简便方法。
one 用于编写 Vector3(1, 1, 1) 的简便方法。
zero 用于编写 Vector3(0, 0, 0) 的简便方法。
Magnitude:返回该向量的长度。(只读)
Lerp:在两个向量之间进行线性插值
MoveTowards:向指定点移动(注意写在Update里)
sqrMagnitude:返回该向量的平方长度
normalized:获取单位化后的向量(只读)。
Cross():向量叉乘。
Dot():向量点乘。
Project():计算向量在另一向量上的投影。
Angle():返回两个向量之间的夹角。
Distance():返回两个向量之间的距离
Quaternion类
Euler返回一个围绕 Z 轴旋转 z 度、围绕 X 轴旋转 x 度、围绕 Y 轴旋转 y 度的旋转
应用实例
Quaternion quaternion_T;
void Start()
{
quaternion_T=Quaternion.Euler(100,30,200);
print("Euler to Quaternion"+quaternion_T);
}
collision类
#region 碰撞检测:两个都是碰撞器,可以获取别的碰撞器
自己是碰撞器-别人也是碰撞器 ****
碰撞检测,检测的是别人(不是挂脚本的物体)
//private void OnCollisionEnter(Collision collision)
//{
// Debug.Log("发生碰撞时");
// Debug.Log(collision.collider.name); //碰撞物体名字
// Debug.Log(collision.collider.gameObject); //碰撞物体
// Debug.Log(collision.collider.tag); //碰撞物体标签
//}
//private void OnCollisionStay(Collision collision)
//{
// Debug.Log("碰撞时");
//}
//private void OnCollisionExit(Collision collision)
//{
// Debug.Log("结束碰撞时");
//}
自己是碰撞器,别人是触发器,触发不了碰撞检测函数
自己是触发器,别人是碰撞器,触发不了碰撞检测函数
#endregion
#region 触发检测:只要有一个触发器,就可以触发 触发检测函数
//自己是碰撞器,别人是触发器,可以触发 触发检测函数
//自己是触发器,别人是碰撞器,可以触发 触发检测函数
//自己是触发器,别人是触发器,可以触发 触发检测函数
private void OnTriggerEnter(Collider other)
{
Debug.Log("发生碰撞时");
Debug.Log(other.name); //碰撞物体名字
Debug.Log(other.gameObject); //碰撞物体
Debug.Log(other.tag); //碰撞物体标签
}
private void OnTriggerStay(Collider other)
{
Debug.Log("碰撞时");
}
private void OnTriggerExit(Collider other)
{
Debug.Log("结束碰撞时");
}
#endregion
射线
第一种写法
#region 射线第一种写法
Camera.main 获取主摄像机
//Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//RaycastHit hit;//存放射线碰撞信息
//if (Physics.Raycast(ray, out hit))
//{
// Debug.DrawLine(Camera.main.transform.position, hit.point, Color.red);
// Debug.Log(hit.collider.name); //射线打的物体名字
// Debug.Log(hit.collider.gameObject);//射线打到的物体
// Debug.Log(hit.collider.tag);//射线打到物体的标签
// Debug.Log(hit.point);//射线与物体的碰撞的点坐标
//}
#endregion
第二种写法
#region 射线第二种写法
//Ray ray = new Ray(obj1.transform.position, obj2.transform.position);
//RaycastHit hit;//存放射线碰撞信息
//if (Physics.Raycast(ray, out hit))
//{
// Debug.DrawLine(obj1.transform.position, obj2.transform.position, Color.red);
// Debug.Log(hit.collider.name); //射线打的物体名字
// Debug.Log(hit.collider.gameObject);//射线打到的物体
// Debug.Log(hit.collider.tag);//射线打到物体的标签
// Debug.Log(hit.point);//射线与物体的碰撞的点坐标
//}
#endregion
高级写法
#region 射线高级写法
//射线另一种写法
Ray ray = new Ray(obj1.transform.position, obj2.transform.position);
//Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
//if (Physics.Raycast(ray, out hit))
if (Physics.Raycast(ray, out hit, 100, 60))//100是射线的长度 2 3 4 5
//if (Physics.Raycast(ray, out hit, 100, ~(1 << 5)))//100是射线的长度
{
Debug.Log(hit.collider.name);
}
//必须加上最大长度 32层
//(1 << layerNumber)只检测某一层(layerNumber表示layer层的标号)
//~(1 << layerNumber)不检测某一层,其余都检测
//(1 << layerNumber)|(1 << layer2Number)只检测某2个层
//int a = 1; //=> 001
//int b = 4; //=> 100
//Debug.Log(a | b); //==101
1010101001==> 1 3 5 7 9
/// 111100
#endregion
WWW类
void Start()
{
//Debug.Log("Start调用1");
//StartCoroutine("MyFun");//调用协程
//Debug.Log("Start调用1");
//StopCoroutine("MyFun");//终止协程
//StopAllCoroutines();//终止所有协程
StartCoroutine(MyFun());//调用协程
StopCoroutine(MyFun());//终止不了协程
}
IEnumerator MyFun()
{
yield return new WaitForSeconds(4);//等待4秒
Debug.Log("协同被调用1");
yield return null; //返回空
Debug.Log("协同被调用2");
}
实例1
public Texture img;
void Start()
{
StartCoroutine("LoadingImage");
}
IEnumerator LoadingImage()
{
string url= "https://img2.baidu.com/it/u=1513792956,895994420&fm=15&fmt=auto&gp=0.jpg";
WWW www = new WWW(url);
yield return www;
if (www.error == null)
{
img = www.texture;
}
}
private void OnGUI()
{
if(img!=null)
GUI.Label(new Rect(0, 0, img.width, img.height), img);
}
WWWFrom类
public string url = "http://127.0.0.1:8089/SharedHome/Owner.aspx";
void Start()
{
StartCoroutine("UpData");
}
IEnumerator UpData()
{
WWWForm wwwForm = new WWWForm();
wwwForm.AddField("Id","999");
wwwForm.AddField("Passworld", "12345");
WWW www = new WWW(url, wwwForm);
yield return www;
if (www.error == null)
{
Debug.Log("上传完成");
}
else
{
Debug.Log(www.error);
}
}
WWW事例1
public Texture img;
public string url = "http://127.0.0.1:8089/1.Txt";
public string urlTxture = "http://127.0.0.1:8089/01.jpg";
public string urlTxture2 = "http://127.0.0.1:8089/02.mp4";
void Start()
{
//StartCoroutine("LoadingImage");
//StartCoroutine("LoadingTxt");
//StartCoroutine("LoadingTexture");
//StartCoroutine(LoadingTexture(urlTxture));
//StartCoroutine("Load");
}
private WWW www;//下载网址信息
public string LoadPro;//下载进度
public IEnumerator Load()
{
www = new WWW(urlTxture2);
yield return www;
while (!www.isDone) //没有 下载完成
{
LoadPro = (((int)(www.progress * 100)) % 100) + "%";//98 %
Debug.Log("进度:" + LoadPro);
yield return 1;
}
if (www.error != null) //报错
{
Debug.Log("Loading error:" + www.url + "\n" + www.error);//打印错误信息
}
else
{
LoadPro = "100%";
Debug.Log("下载完成");
}
}
/// <summary>
/// 读取图片
/// </summary>
IEnumerator LoadingTexture(string url)
{
WWW www = new WWW(url);
yield return www;
//www.isDone//属性以查看下载是否完成
//www.progress//下载进度(只读)
if (www.error == null)
{
img=www.texture;
}
else
{
Debug.Log(www.error);
}
}
/// <summary>
/// 读取txt信息
/// </summary>
IEnumerator LoadingTxt()
{
WWW www = new WWW(url);
yield return www;//等待访问结束
if (www.error == null) //如果下载期间出错,则返回错误消息(只读)
{
Debug.Log(www.text);
}
else
{
Debug.Log(www.error);
}
}
IEnumerator LoadingImage()
{
string url= "https://img2.baidu.com/it/u=1513792956,895994420&fm=15&fmt=auto&gp=0.jpg";
WWW www = new WWW(url);
yield return www;
if (www.error == null)
{
img = www.texture;
}
}
//private void OnGUI()
//{
// if(img!=null)
// GUI.Label(new Rect(0, 0, img.width, img.height), img);
//}
UnityWebRequest 类
事例1
public string url= "http://127.0.0.1:8089/02.mp4";
void Start()
{
StartCoroutine("LoadingDate");
}
IEnumerator LoadingDate()
{
UnityWebRequest request = UnityWebRequest.Get(url); //UnityWebRequest对象用于与 Web 服务器进行通信。
/*
Get 为 HTTP GET 创建 UnityWebRequest。
Head 创建一个经配置可发送 HTTP HEAD 请求的 UnityWebRequest。
Post 创建一个经配置可通过 HTTP POST 向服务器发送表单数据的 UnityWebRequest。
Put 创建一个经配置可通过 HTTP PUT 将原始数据上传到远程服务器的 UnityWebRequest。
*/
request.SendWebRequest();//开始与远程服务器通信
/* isHttpError:当此 UnityWebRequest 接收到指示错误的 HTTP 响应代码后,返回 true。(只读)
* isNetworkError:当此 UnityWebRequest 遇到系统错误后,返回 true。(只读)
* error:一个可读字符串,用于描述此 UnityWebRequest 对象在处理 HTTP 请求或响应时遇到的任何系统错误。(只读)
*/
if (request.isHttpError || request.isNetworkError)
{
Debug.Log("当前的下载发生错误" + request.error);
yield break;
}
while (!request.isDone) //isDone:当 UnityWebRequest 结束与远程服务器的通信后,返回 true。(只读)
{
print("当前的下载进度为:" + request.downloadProgress); // downloadProgress 返回一个 0.0 和 1.0 之间的浮点值,用于表示从服务器下载主体数据的进度。(只读)
yield return 0;
}
if (request.isDone)
{
//将下载的文件写入
using (FileStream fs = new FileStream(Application.dataPath + "/Test.MP4", FileMode.Create))
{
byte[] data = request.downloadHandler.data; //downloadHandler:拥有对 DownloadHandler 对象的引用,该对象可管理此 UnityWebRequest 从远程服务器接收的主体数据
fs.Write(data, 0, data.Length);
}
}
}
事例2
void Start()
{
StartCoroutine(Get());
StartCoroutine(Post());
}
IEnumerator Get()
{
UnityWebRequest webRequest = UnityWebRequest.Get("http://www.baidu.com");
yield return webRequest.SendWebRequest(); //开始与远程服务器通信。
//异常处理,很多博文用了error!=null这是错误的,请看下文其他属性部分
if (webRequest.isHttpError || webRequest.isNetworkError)
Debug.Log(webRequest.error);
else
{
Debug.Log(webRequest.downloadHandler.text);
}
}
IEnumerator Post()
{
WWWForm form = new WWWForm();
//键值对
form.AddField("key", "value");
form.AddField("name", "mafanwei");
form.AddField("blog", "qwe25878");
UnityWebRequest webRequest = UnityWebRequest.Post("http://www.baidu.com", form);
yield return webRequest.SendWebRequest();
//异常处理,很多博文用了error!=null这是错误的,请看下文其他属性部分
if (webRequest.isHttpError || webRequest.isNetworkError)
Debug.Log(webRequest.error);
else
{
Debug.Log(webRequest.downloadHandler.text);
}
}