Unity基础
unity note:
游戏和三维互动内容开发工具,专业游戏引擎
#前言
游戏引擎: 一款游戏最核心的代码
包含: 渲染引擎,物理引擎、碰撞检测,音效、脚本引擎、动画系统
人工智能、网络引擎、场景管理。
游戏公司分工
策划、美工、软件工程师、测试工程师。
首月:
day1:
环境搭建、C#语言基础、Unity API、物理引擎1、3D数学基础、UGUI
- 程序界面
Project->Assets文件
Hierarchy-> 对象
Scene 右键旋转 滚轮->前进后退 F键—>居中
Alt+左键 围绕旋转 WSADQE同时:场景漫游
Inspector: 检查监视面板
Transform -> Position 坐标
3d->cube 顶点吸附 按V键
Pivot - Center 设计坐标-中心坐标
Global - Local 世界坐标-自身坐标
视图: IOS(2D) - Persp(透视)3D
—》可以在设计界面右上角调节
世界坐标: 场景坐标
本地坐标: 物体自身坐标
场景: 一组相关联的游戏对象的集合。
游戏对象: GameObject ->容器—>组件->{
功能的模块{
Transform变换组件、
MeshFilter网格过滤器、
Mesh Render 网格渲染器}
}
day02:
1.材质material:
色彩,文理、光滑度、透明度、反射率、折射率、发光度。
png使用较多,psd(photoshop文件)
png文件图片质量高。
材料模式(Render mode):
opaque 不透明的.
cutout(去掉透明通道)->剪裁 设定阈值,低于阈值直接消失。
Fade(渐变) -> 常见的透明度渐变要这个模式。比较消耗性能
Transparent(透明)要设透明度,用于实现窗户的效果。
shader 着色器: 渲染管线,控制GPU
Shader->Material{Texture(材质),Color}->Object
渲染管线: 重点: 面试必考
{
几何阶段 -> 打线稿
{
顶点处理
。。。
待补充
}
光栅化阶段 -> 像素画,着色
{
片元作色
像素化
待补充
}
2. 摄像机camera:
在一个场景中出现数量不限,显示方法-》视锥
组件:
Transoform变换组件
camera
flare Layer 耀斑层
audio listener 音频监听器:接收场景输入的音频
camera-> Clear Flags: 处理屏幕空白部分
-> 天空盒 - 模拟天空材质
-> 6面组成,程序的。
material-> shader->skybox
->DepthOnly ->去除白色部分
使用-> a. 摄像机添加-addcomponent-> skybox
b. 光照窗口(物体可反射颜色,常用) Windows->Lighting->skybox
-> Procedural 有太阳、只有2种(天、地)。
Culling Mask 去除层。 将某层元素去除。该层不渲染
Projection(投射) Perspective(透视的,三维的视角)/orthographic(直角的)-> 去除纵深
Clipping Plane : Far设置视距 Near: 多远才能看到
Viewport Rect: X,Y,W,H : XY视窗坐标,WH设置视窗大小
可实现分屏。
Depth map的depth大于主摄像机,map摄像机才能显示
(要在前面的深度值高)
3.InstantOc 渲染管线:
图形数据在GPU上经过运算最后输出到屏幕的过程
游戏-> 图形API -> GPU -> 顶点处理-> 光栅化-> 显示器
Draw Call : 准备数据并通知GPU的过程,每帧调用显卡渲染物体的次数
= Batches
↓顶点处理: 接收模型顶点数据。顶点转换
↓图元装配: 组装面
↓光栅化: 计算三角面上的像素
↓像素处理: 对每个像素区进行着色
↓缓存: 帧缓存/深度缓存z-buffer
Occlusion culling: 遮挡剔除 将摄像机视角内看不到的物体剔除,提升渲染性能
新版unity已经不需要装插件了,可以直接在Camera 组件上勾选。
https://blog.csdn.net/qq_33537945/article/details/79159070
步骤-> 将参与剔除的物体标记遮挡静态(Occluder Static/Occludee Static)
Windows-> OcclusionCulling 单击下方Bake
API
IOC layer 层
IOC Tag 层标签
simples 采样率一般在150-500之间
Rays FOV 和摄像机field of view 一致
View Distance 参考摄像机Far
Hide Delay 当前物体被剔除时延迟的帧数。一般50-100之间。
PreCull Cheack : 检查采集信息
Realtime Shadows : 实时阴影
LOD: Layer of detail 实现分级渲染
步骤->多精度模型加入父类object,父类object添加LOD Group
优点: 节省GPU
缺点: 占内存(比如三级精度的话就存放了3个模型)
物体添加-> Box Collider 添加碰撞箱
4. 光照系统:
Global Illumination 全局光照
GI: 直接光、间接光、环境光、反射光。
light选项: 方向、color、Intensity、Culling Mask
Type: Spot聚光灯、Direction方向光、Point(灯泡)、Area
Culling mask: 照射选定层
<8,10,12章> 《3D数学基础》15章 :图形数学
day03
-
阴影: Light-> Shadow Type:有无阴影,软硬阴影
strength:强度
Receive Shadow:接收阴影
mesh Render - >Cast shadow-> 只阴影,无阴影,双面阴影
阴影剔除
:节省资源
edit-> project setting -> shadow->distance -
环境光: 作用于场景内所有物体的光照。
Lighting -> Environment Lighting -> Ambient
source: 环境光来源
Intensitive: 强度 -
反射光: 根据天空盒计算的作用于-- > 消耗性能
Lighting -> Environment Lighting ->reflection -
间接光照
Light-> Bounce Intensity -
实时GI
运行时改光源,运行时产生间接光。开发期间做了预计算
Edit -> Perferences->GI Cache -
烘焙GI
https://blog.csdn.net/leeby100/article/details/99827850
将光线效果预渲染成贴图再作用到物体上模拟光影
Light-> Baking
Baked GI
游戏对象设置为Lightmaping Static。
设置Light Baking 属性
7.光源侦测
物体感受bake的光源。 小球储存光影信息。
Creat-> Light Probe Group -
声源: 支持的音频格式:
mp3,ogg,wav,aif,mod,it,s3m,xm
声音分为2D,3D
3D:空间感,2D背景音乐
Audio Listener: 声音监视器
Audio Souce: 声音源
Audio->Audio Source
3D Sound Setting
rolloff 衰减方式
Audio listener Audio
day03:
C#编程基础
.NET dotnet 新一代多语言开发平台。
c# csharp
Mono 支持在其它操作系统下开发.NET程序框架
Unity 借助Mono实现跨平台
day04:
P24
C#编程
类->方法
->属性
命名空间-> 类-> {方法,属性}
using … 引入命名空间
CTRL+K+F -> 自动对齐
CTRL+K+C -> 注释选中的代码
CTRL+K+U -> 取消注释
整数
sbyte 1个字节有符号8位
byte 1个字节无符号8位
short 2个字节有符号16位
ushort 2个字节无符号16位
int 4字节
uint 4字节
long 8字节
ulong 8字节
浮点数
float 4字节单精度浮点
double 8字节双精度浮点型
!decimal 128字节,精度28-29位、适用于财务和货币计算
C#的float赋值必须加f
decimal赋值必须加m
float a = 0.3f;
decimal a = 2.9m; ->2.9的意思
->
浮点型运算会有舍入误差
字符
char 2字节,使用单引号
string 字符串,双引号
布尔型
bool 1字节,1,0
调试: 打断点-> F5调试-> F11执行下一行
Shift+F5 结束调试
直接输出结果 ctrl+F5
强制类型转换
字符串等转整数
1.(int)… (这个只适用于浮点数转换)
2.Convert.ToInt32(string)
3.int.Parse(string)或 int.TryParse(String,out int)
输出流:例子
Console.WriteLine(“枪名:”+gunName+ “\t弹匣容量:”+ magazineNum + “\t弹匣内子弹数量:” + currentMagazineNum + “\t当前子弹数量:” + currentbulletNum);
格式占位符
string a = string.Format("{0},{1}",a,b);
{0:d2} 5 -> 05 15-> 15 2位显示
{0:f1} 1.23-> 1.2 1.26-> 1.3 1位小数
" \ -> 转义符
《c#入门经典》 变量与变量表达式
《代码大全2》 10章,11章
day05
dotnet
Mono
CLS : 公共语言规范 定义.net平台上运行的语言规范
CLR :公共语言运行库。 exe->CLR编译(汇编)-> 机器码
.cs文件-> CLS -> .exe -> CLR -> 010100011
运算符:
赋值运算符: =
运算符: + - * / %(取模)
比较运算 < > <= >= == !=
逻辑运算 && || !
快捷运算符 += *= /= %=
一元运算符 ++ –
二元运算符 = a + b
三元运算符 string a = 1>2?“3”:“4”
优先级 …
-
string转换为 其它类型
int.Parse
… -
Tostring : 任意类型转换为string
int number = 18;
string str = number.Tostring(); -
隐式转换, 自动转换;
byte b3 = 100;
int i3 = b3; -> TRUE
4.显式转换 : 强制转换;
int i3 = 100;
byte b3 = (byte)i3;
判断一个数奇偶性: bool r3 = a1%2 == 0;
定义字符数组
char[] a = new char[4];
byte b=250;
b+= 7; 快捷运算符,可实现,不会自动提升类型
b = (byte) b+7; 会转换为int
语句: 选择语句、循环语句、
if(…)
{
…
}
else if(…)
{
…
}
else
{
…
}
短路逻辑: && 和||
与出现0,或出现1 都不再执行后项
day06 、
!!!
C#在函数内定义的变量为局部变量,循环结束后失效
循环语句:
for(; ; ) {…continue …break…}
while(){} …
do{} while()
foreach(var variable in Arr){…}
注释// /**/
!创建随机数
Random random = new Random();
产生一个随机数
int number = random.Next(1,101);
跳转语句: continue、break、return goto
函数(方法):
[访问修饰符][可选修饰符]返回类型 方法名称(参数列表)
{
…
}
private static void Fun1(){} //函数首字母大写
返回类型: int double short float string decimal void
day 07:
函数重载,根据参数数量判断。
名称相同,返回值相同。
递归: …函数自调用
优点: 复杂简单化
缺点: 性能差,难以理解
取绝对值: ststem.math.abs()
数组:
int[] a;
a = new int[6];
-> int[] a = new a[3]{1,2,3};
初始化+赋值
a.Length
Array.Clear(a) 清除元素值
Array.Copy(a)
a.CopyTo
a.Clone
Array.IndexOf(a,num) Array.LastIndexOf(a,num)
Array.Sort(a)
Array.Reverse(a)
static float[] Createasdas(){
return scoreArray; -> 返回数组
}
day 08:
//从头到尾
foreach(int var in arr){
}
二维数组
创建二维数组:
int[,] a = new int[3,5]={0}; //初始化后全为0
2048
Arr.Length -> 获得总长度
Arr.GetLength(0或1) ->获得行数量,列数
day 09:
交错数组:每一个元素中间可以套数组。
4元素交错数组
int[][] array02;
array02 = new int[3][];
array02[0] = new int[3];
array02[1] = new int[5];
array02[2] = new int[2];
array02: [
000
00000
00
]
赋值-> array02[0][0] = 99;
foreach(int[] array in array02){
foreach(int i in array){
…
}
}
!!参数数组
!!static int Add(params int[] arr) -> 传参数数组
params
1.可传递数组、传递一组数据类型相同的变量集合
2.可以不传递参数
params int[] arr; 参数数组
可以实现 -> Add(1,23,4,6,8,3,4);
不需要输入数组也可进入函数,自动转换为数组进入函数。
== Add(new int[]{1,23,4,6,8,3,4});
数据类型->
值类型 -> 数据本身,声明在栈中,数据存储在栈中
结构-> int,bool,char
枚举-> enum
引用类型 -> 存储数据的引用(内存地址),声明在栈中,数据存储在堆中
接口->
类 -> string,int[],object
栈区:存储正在执行的方法, 值类型
堆区:存储引用类型的数据: 类 new 出来的类型。
string s1 = "男"; == new string[]{...};
!引用类型声明赋值 相当于new。
!!!引用参数ref :
static void Fun2(ref int a){…}
使用 :Fun2(ref a2);
必须有值才能进入,否则报错。内部可更改数据。
直接对地址能数据进行操作。
!!!输出参数out : 按引用传递–传递实参变量的内存地址
函数内部必须赋值,否则报错。
static void Fun3(out int a){…}
使用 :Fun3(out a2);
ref out区别:1. 使用ref 前必须对ref 参数赋值
使用out 在函数内部中必须对其赋值,传递之前可不赋值;
使用out实现有多个返回值的函数。
int a;
bool re = int.TryParse(“250”,out a);
垃圾回收器: GC 针对托管堆自动回收释放内存的服务
拆装箱:
int a = 1;
object b = a; //装箱操作: “比较消耗性能”
装箱box: 值类型隐式转换为Object类型。
1.在堆中开辟内存空间。
2.将值类型的数据复制到堆中。
3.返回堆中新分配对象的地址。
int b = (int)o; //拆箱操作:
拆箱unbox: 从object类型到值类型
1.判断是不是装箱时的类型
2.返回已装箱实例中属于原值类型的地址。
形参object,实参值类型,则会发生装箱
通过重载、泛型可避免拆装箱
string str02 = “” + num;
//string str02 = string.Contact(params object);
存在装箱操作
bool r1 = object.ReferenceEquals();
//判断存的是不是同一个
字符串池。
object a = 1;
a = 2.0;
a = “OK”;
a = true; //object每次修改都是开辟新的空间
字符串拼接:! 防止造垃圾。
StringBuilder bulider = new StringBuilder(10);
for (int i = 0;i<10;i++){
bulider.Append(i);
}
string result = bulider.Tostring();
bulider.Insert;
string 方法:
ToArray Insert
Contains ToLower
ToUpper IndexOf
Substring Trim :去除开头的字符串
Split Replaace
Join
day10:
枚举:
定义枚举类型:
enum MoveDirection{
Up = 0,
Down = 1,
Left = 2,
Right = 3
}
简单枚举: 列举某种数据的所有取值
增强可读性,限定取值
枚举的多选 enmu a | b
|按位或运算符。
p91
1.任意多个枚举值做|运算,结果不能和其它枚举值相同
2.定义枚举时,使用[flags],表明可以多选
[Flags]
enum PersonStyle{…}
:定义标准枚举
&按位与运算
|按位或运算
^非
Enum.Parse(typeof(PersonStyle),"…");
!类和对象
创建类;
访问级别 class 类名
{
类成员…
}
通常每个类在一个独立的c#源文件中
创建新的类意味着在当前项目中创建了一个新的数据类型
this.name = name;
类 对象;
对象 = new 类();
成员变量: 类中方法外的变量,具有默认值,默认为null。
访问修饰符
!字段,属性: 字段首字母小写,属性首字母大写
!属性:对字段起保护作用。可实现只读,只写…
public int Age{
get{
return this.age(字段); //获得age字段值返回
}
set{
this.age(字段) = value; //value为获得属性,直接写value
}
}
只读: 只有get 只写:只有set
构造函数:初始化类的数据成员
public 类名(…参数)
{
…
}
对没有构造函数的类会提供一个空构造函数。
构造函数可以重载
如果不希望在类的外部被创建对象,
可以将构造函数私有化。
单例
调用无参数构造函数:继承?
public 类名(…参数):this(…) !调用无参构造,或者this()里面加参数
{
}
构造函数重载+嵌套。
this 关键字:
一个标准类:
class User
{
//字段
private string loginId;
//属性
public string LoginId;
{
get{
return this.loginId;}
set{
this.loginId = value;}
}
public string Password{
get;set;} //这个是语法糖
//构造函数
public User()
{
}
public User(string id,string password):this(id)
{
}
//方法
public void PrintUser()
{
console.WriteLine(....);
}
}
data.CopyTo;
VS快捷键 Ctrl+m 将选定列提取出函数
day10:
C# 集合
列表集合:
List<数据类型(int,char)>
List<User> list02 = new List<User>();
list02.Add(u1);
list02.Add(new User());
字典集合:
Dictionary<键,值>
Dictionary<string,int>
Dictionary<string,User> dic = new Dictionary<string,User>;
dic.Add("123",new User("123",123));
User lhUser = dic["lh"];
//prop +tab+tab -> 快速创建属性
!继承:
public class Son:Father
{
...
}
public:公开,都可以用
private:Father的,Son继承了但不能用。
protected级别:Fahter,Son可以用,别人不能用
//父类型的引用指向子类对象
//只能使用父类成员
Father person02 = new Son();
//要使用子类的要强转
Student stu02 = (Student)person02;
//↓如果转换失败就出错。
Teacher teacher02 = person02 as Teacher;
Static:静态
类变量和成员变量的区别。
Static 变量使用类名调用
private static int ascxv;
修饰成员变量: 静态成员变量属于类,实例成员变量属于对象
!静态: static
静态区: 单独存储。
静态构造函数:初始化类的静态数据成员
static Student()
{
...
}
仅在类加载时调用一次
静态方法:只能访问静态成员。
this在静态方法中无效
静态类
使用static修饰的类:
不能实例化、只能包含静态成员。
不能被继承、但静态方法,属性可以被继承
利:单独空间存储、所有对象共享、可以直接被类名调用。
弊:静态方法只能访问静态成员、共享数据被多个对象访问会出现并发。
适用场合:
1.所有对象要共享的数据。
2.没有对象前要访问的成员。
3.工具类适合做静态(常用,不需要过多数据)
(Math.Abs(),…)
结构体:
用于封装小型相关变量的值类型
结构属于值类型,类属于引用类型
struct Direction{
//只有两只方法可以赋值:
//const(常量)、static
public int RIndex{
get;set;}
public Direction(int r,int c):this()
{
//如果有自动属性 {get;set;},必须先调用this()
this.RIndex = r;
}
}
结构体自带无参构造函数
2048 核心类
Unity编程
day11:
脚本:
.cs的文本文件 类文件
附加在游戏物体上用于定义游戏对象行为指令代码
using 命名空间;
public class 类名:MonoBehaviour
{
void 方法名()
{
...
}
}
!文件名与类名必须一致
!写好的脚本必须附加到物体上才执行
!附加到游戏物体的脚本类必须从MonoBehaviour类继承
编译过程:
源代码–CLS->中间语言(DLL)–(Mono Runtime) -> 机器码
脚本就是一个类
Update() ->0.02会调用一次
!!!!
父类有Update子类不会调用,解决方法-> 虚方法重写
父类->
protected virtual void Update(){
}
子类->
protected override void Update(){
}
public calss Demo01:MonoBehaviour
{
}
!脚本生命周期(消息、必然事件):
unity脚本从唤醒到销毁的过程。
[SelectionBase] //序列化字段
private int a = 100;
加上标签-> 私有变量显示在编译器中。
[HideInInspector]
public int b;
在编译器中隐藏字段
[Range(0,100)]
public int c;
在编译器中限制c的取值
unity脚本里面看不到属性。
unity中的脚本生命周期:
//字段
//方法(函数)
//脚本中不写构造函数
/***************初始阶段:*******/
Awake: //执行时机: 创建游戏对象 立即执行
作用:初始化
Start: //执行时机: 游戏对象创建->脚本启用->执行
作用:初始化,充当构造函数
OnEnable: //执行时机:当脚本对象启用时调用
private void Awake()
{
Debug.log("Awake" + Time.time + "--"+this.name);
}
private void Start()
{
Debug.log("Start" + Time.time + "--" + this.name);
}
private void OnEnable(){...}
/********************物理阶段*****************/
FixedUpdate 固定更新:
//执行时机,每固定时间(0.02s)执行一次
脚本启用后:固定时间被调用:适合对对象做物理操作
设置更新频率: "Edit" --> "Project Setting" -->
"Time" --> "Fixed Timestep" 值,默认为0.02s
private void FixedUpdate()
{
//渲染时间不固定(渲染质量不同、配置不同)
Debug.Log(Time.time);
}
Update 更新
//执行时机: 渲染帧执行、执行时间不固定
//适合性: 处理游戏逻辑
private void Update()
{
}
LateUpdat 延迟更新:
//防止发生相机先手人后走的情况发生
//执行时机: 在Update被调用后执行,适用于跟随逻辑
private void LateUpdate()
{
}
/******************输入事件*************************/
OnMouseEnter 鼠标移入 需要碰撞器
OnMouseOver 鼠标经过
OnMousExit 鼠标离开
OnMouseDown 鼠标按下
OnMouseUp 鼠标抬起
/*****************场景渲染*********************/
OnBasecameVisible 当可见
当Mesh Renderer 在任何相机上可见时调用
OnBecameInvisible 当不可见:
当Mesh Renderer 在任何相机上不可见时调用
/*****************结束阶段**********************/
OnDisable 当不可用
当对象变为不可用或附属游戏对象非激活状态时调用
OnDestory 当销毁:
当脚本销毁或附属游戏对象被销毁时调用
OnApplicationQuit 当程序结束:
应用程序退出时调用
文档-> 索引 -> monobehaviour
脚本生命周期:
AWake -> OnEnable -> Start
FixedUpdate->>>>>>OnCollision↓
↑ <<<<<< ←(或↓)
yield WaitForEndOfFrame->OnApplicationPause
…
具体详查脚本生命周期图 面试必考
https://www.cnblogs.com/android-blogs/p/6148188.html
-> OnDestory->OnApplicationQuit
Unity编辑器:
1.控制台调试 Debug.Log(变量);
print(变量);
-
定义public变量,在程序运行后在控制台中看
-
VS调试
//快速监视
//即时窗口
逆向: p118
print继承自monobehaviour
单帧调试 -> 启动调试 运行场景 暂停游戏
加断点 单帧执行 结束调试
!常见API:
**
Unity核心类
http://www.ajnote.com/unity-%E6%A0%B8%E5%BF%83%E7%B1%BB%E5%9B%BE/**
**Component:**
{
提供了(在当前物体、后代、先辈)查找组件的功能;
this.transform.position = new vector3(0,0,10);
//改坐标
this.GetComponent<Renderer>().material.color = Color.red;
//改颜色/改材质。。
文档->Function->GetCompent
//获取当前物体所有组件
if (GUILayout.Button("Components")) {
var AllComponent = this.GetComponents<Component>();
foreach (var item in AllComponent) {
print(item.GetType());
}
所有子物体,包括后代的同一组件
getComponentsInChildren<Render>().color = color.red;
不带s,只找自己的组件。
getComponentInChildren<Render>()
//往上找所有祖宗
getComponentsInParent<>();
//只找上一代
getComponentInParent<>();
//对比标签是否一样。可以直接==
CompareTag
}
Transform:
{
//通过当前变换组件获得每个子物体的变换组件
foreach (Transform Child in this.transform) {
print(Child.name);
transform.position :在世界坐标系的位置
localPosition: 相对于父物体轴心点的位置
rotation/localrotation
localScale: 相对于父物体的缩放比例
lossyScale: 物体与模型缩放比例,相对于世界(只读)
//父3,自身local:2, lossyScale 为6
方法(函数):
Translate: 移动指定方向的距离。
this.transform.Translate(0,0,1);
//向自身z轴移动一米
this.transform.Translate(0,0,1,Space.World);
//基于世界坐标系移动
Rotate: 转动
//y轴转动10度(沿自身,沿世界)
this.transform.Rotate(0,10,0)
this.transform.Rotate(0,10,0,Space.World)
//沿选定轴旋转旋转
RotateAround
this.transform.RotateAround(Vector3.zero,Vector3.up,1);
//参数:点、轴、角度 例子:绕零点,y轴转1度,通过repetButton实现连续旋转
//获取根物体:
Transform rootTF = this.transform.root;
//获取父物体
Transform parentTF = this.transform.parent;
//改爸爸-> 拿起物体
this.transform.SetParent(Transform x);
//找孩子根据名称
this.transform.Find(子物体名称);
//找孙子
this.transform.Find(子物体名称/子物体名称);
//根据索引找孩子
int count = this.transform.childCount;
this.transform.Getchild(i)
//i=0;i<count;i++
//解除父子关系
DetachChildren
//解除父亲关系
SetParent(null);
//找兄弟索引
GetSiblingIndex
//改变兄弟等级
SetAsFirstSibling
SetAsLastSibling
拖物体归属-> 改变变换组件(Transform)
}
GameObject
{
ActiveSelf
//只读——> 该对象的局部激活状态
activeInHierarchy
//场景中的游戏对象是否激活?
//父未激活则无效
isStatic
layer
scene
tag
transform
}
方法:
添加组件的几种方法:
{
1.gameObject.AddComponent<...>();
2.[RequireComponent(typeof(...))]
3.直接添加,拖拽
}
**AddComponent**{
添加组件
GameObject lightGO = new gameObject();
Light light = this.gameObject.AddComponent<Light>();
light.color = Color.red;
light.type = LightType.Point;
}
SetActive(bool) -> 设置物体的启用和禁用
//在场景中根据名称查找物体(慎用)
!GameObject.Find("游戏对象名称")
//获取所有使用该标签的物体
FindGameObjectsWithTag;
//获取使用该标签的物体
FindWithTag(...)
this.transform.Find("..");
}
Object
{
Destroy
删除组件 -> destory
Destroy(gameObject,5)
//5s后销毁对象
DestroyImmediate 立即删除,不建议使用
DontDestroyOnLoad 加载新场景时不自动清楚该对象
!//根据类型查找一个对象
!FindObjectOfType<>();
//根据类型查找所有对象
FindObjectsOfType<>();
Instantiate-> 克隆原始物体并返回克隆物体
}
task0809_01 :组件-> Hp
task0809_02 :按钮对象
day12:
LookAt: 注视旋转
!Time类
{
只有静态变量
time: 以秒计算、游戏开始的时间。
!deltaTime: 完成最后一帧的时间。
!-> △t ->
!渲染量-> 帧数多 1s -> 一帧动作小
! 帧数少 1s -> 一帧动作大
-> 相同距离-> 总速度恒定。
!this.tranform.Rotate(0,1*Time.deltaTime,0);
保证旋转/移动-> 不受渲染影响。
!timescale->时间的倍数->实现倍速,慢动作,暂停
timescale>1 加倍
timescale <1 慢动作
timescale = 0 暂停-> FixedUpdate不再更新
但是Update不受影响(原因-> Update受渲染影响)
timescale=0 -> deltaTime会受影响->实现在Update的暂停
fixedDeltaTime;
unscaledDeltaTime->不缩放的帧时间。
->实现游戏暂停时部分物体可以运动。
}
在Start中使用
InvokeRepeating(“Timer”,1,1);
//重复调用(被执行的方法名称,第一次执行时间,每次执行间隔)
CancelInvoke(…) //取消重复调用
///3种方法实现计时
///1. Tol = Time.time; Tol >NextTime? NextTime = Time.time +1 ->Update
///2. Tol += Time.deltaTime ?.. Tol = 0 ->Update
///3. InvokeRepeat(“Timer”,1,1); CancelInvoke(…) ->Start
Invoke(…);
(被执行的方法,开始调用时间)
方法1-> 先做一次
方法2-> 先等
方法3-> 简单循环事件
预制件Prefabs
{
Select : 通过预制件实例选择对应预制件
Revert :重置为初始状态
Apply: 将该实例的修改引用到所有实例中
从Hierarchy拽到Project面板
一种资源类型->可以多次在场景进行实例,提高开发效率
可以实现特殊值,改单个
}
day13
动画
通过动画视图可以直接创建和修改动画片段
Animation View
Window—Animation
创建动画片段 ->物体添加Animation组件
时间线 1:30 -> 1秒和30帧 默认1s->60帧
OnMouseDown-> …
Animation类
{
方法:
Play
CrossFade -> 淡入淡出 -> 两动画之间过渡
PlayQueued -> 队列播放
属性
!speed 0 -1 1 2 ....
播放速度->可以实现倒放
anim["Door"].speed = 1;
length
time
wrapMode ->播放模式(一次,循环,往复播放,固定点一次。)
(once,loop,ping pong,clamp forever)
}
day14
{
敌人
a.需求->分析->实现
{
1.敌人沿指定路线运动
2.受击后减血死亡
3.到达终点攻击玩家
4.运动播放运动动画,攻击动画,死亡动画,间隔动画
分析-> 每个事情分类
脚本1-> 敌人马达EnemyMotor -> 移动,旋转,寻路
脚本2-> 敌人状态信息EnemyStatusInfo -> 血量、提供受伤、死亡等功能
脚本3-> 敌人动画EnemyAnimation -> 定义动画,播放动画
脚本4-> 敌人AI EnemyAI,通过判断状态,执行寻路或攻击
}
敌人生成器
b.需求->分析->实现
1.开始时生成指定数量的敌人
2.为每人随机选择一条可以使用的路线
3.敌人类型
4.玩家打死一个后生成新的,直到生成数量达到上限
分析
创建根路线并添加多条子路线
脚本1-> 敌人生成器 EnemySpawn
附加提供生成敌人的功能,附加到根路线提供生成敌人的功能
类-> 路线WayLine
}
Enemymotor
{
MoveForward();
LookRotation(); -> 注视旋转
//transform.lookat
bool Pathfinding(); -> 寻路是否完成,沿路线移动
//朝向目标点
//向前移动
}
EmenyStatusInfo
{
int Hp;
int maxHp;
Damage();
Death();
//播放死亡动画
//销毁对象
}
EmenyAnimation
{
string runAnimName;
... attackAnimName;
... idleAnimName;
... runAnimName;
... deathAnimName;
//动画行为类
public AnimationAction action;
private void Awake()
{
action = new AnimationAction();
}
}
动画行为类,提供动画行为。
public class AnimationAction
{
private Animation anim;
获得动画。
public animationAction(Animation anim)
{
this.anim = anim;
}
//播放动画
public void Play(string animName)
{
anim.CrossFade(animName);
}
}
敌人AI
EmemyAI
{
public enum State
{
Attack,
PathFinding
}
private State currentState = State.PathFinding;
Update(){
判断
执行攻击,
执行寻路
switch(currentState)
{
case State.PathFinding:
//执行寻路
//播放跑步动画
//如果寻路结束切换状态为攻击
case 攻击:
//攻击不能一直攻击,攻击一阵之后要播放闲置动画
//
break;
}
}
}
敌人生成器
先创建路线类
public class WayLine
{
//创建路点数组
public Vector3[] WayPoint{
get;set;}
//路点是否可用
public bool IsUsable{
get;set;}
}
EnemySpawn -> 计算所有路线及坐标,生成一个敌人
{
//需要创建的敌人预制件数组
public GameObject[] enemyType;
//最大敌人数量
public int maxCount = 5;
//开始同时创建敌人数目
public int startCount = 2;
//已经创建的敌人数量
private int spawnedCount;
public void GenerateEnemy()
{
//选择一条可以使用的路线
//延迟时间随机
//Instantiate(敌人预制件,位置,旋转角度);
int randomIndex = Random.Ranage(0,enemyType.Length)
GameObject AnEenemy =
Instantiate(enemyType[Random.Range(0, enemyType.Length)], line.WayPoints[0], Quaternion.identity);
//这句话创建了一个敌人对象,并赋初点
//配置信息,马达
go.getConpent<enemyMotor>
//传递生成器对象引用[建议使用委托的方法来做]
//因为只需要调用对象的方法
//目前传递了对象
AnEenemy.GetComponent<EnemyStatusInfo>().spawn = this; //将本生成器地址传给状态对象
}
路线随机,
计算敌人路线
创建所有路线
选择一条可以使用的路线(WayLine-> IsUsable = true)
随机挑出一条
随机时间随机
}
day15
{
Input类: 包装了输入功能的类
//获取鼠标输入
指定鼠标按钮被按下时返回true
//鼠标按钮被按下
bool result = Input.GetMouseButton(0);
bool result = Input.GetMouseButtonDown(0); 这两个只有一帧返回true
bool result = Input.GetMouseButtonUp(0);
0->左键 1->右键 2->中键
Input 一般在Update调用
//获取键盘输入
bool result = Input.GetKey(KeyCode.A)
bool re