这里写自定义目录标题
- 一,Unity编辑器的学习
- 1.1 API
- 1.1.1 Application 应用程序
- 1.1.2 AudioSource 音频源
- 1.1.3 Camera 摄像机
- 1.1.4 CharacterController 角色控制器
- 1.1.5 GameObject 游戏物体
- 1.1.6 Input 输入
- 1.1.7 MonoBehaviour Mono行为
- 1.1.8 Physics 物理学
- 1.1.9 Quaternion 四元数(物体的旋转)==效果好,游戏用==
- 1.1.10 Random 随机
- 1.1.11 Time 时间
- 1.1.12 Transform 变换
- 1.1.13 Vector3 三维向量
- 1.1.14 【纹理贴图】简析(AO, Normal等)
- 15.Animation 动画(Legacy、Generic和Humanoid)
- 1.2 游戏物体运动方法
- 1.3 游戏NGUI插件的使用方法
一,Unity编辑器的学习
1.1 API
1.1.1 Application 应用程序
1.1.2 AudioSource 音频源
1.1.3 Camera 摄像机
camera第一个属性:
SkyBox天空盒,(没有天空遮挡的地方默认填)
SolidColor固体颜色,
DepthOnly景深度,
DontClear不清楚
第二个属性:背景颜色
第三个属性:遮罩层,层取消勾选可以达到隐藏物体的效果
第四个属性:透视,正交
第五个属性:摄像机广角
第六个属性:距离的剪切
第六个属性:深度 默认-1,最高,渲染只会选择最高的摄像机
第七个属性:目标纹理(做角色影子可以用到)摄像机照射的可以直接显示在一张贴图上
1.1.3.1 固定视角的跟随移动(偏移向量恒定不变)
1.将摄像机置于物体下方作为物体子集(最简单)
2.代码方法:
设定目标:定义一个Player的Transform
偏移向量Offset(玩家-相机 = 相机指向玩家的向量)
摄像机的位置=(玩家的位置与偏移值的矢量关系)
在物体角色移动时用FixedUpdate而相机跟随使用Update时,相机可能会跟随主角的过程中抖动但是相机跟随一般是等跟随目标先移动,然后再执行跟随的代码。但是执行的顺序不是固定的,所以会出现抖动情况。
解决办法:相机放到 LateUpdate 函数里,因为 LateUpdate 是在所有 Update 方法调用后被调用,这样就解决了人物在移动过程中,摄像机抖动的现象。
1、Update():每一帧执行时,都会立即调用此方法。
2、LateUpdate():LateUpdate 是在所有 Update 方法调用之后被调用(语出圣典)。
3、FixedUpdate():固定更新。默认情况下,系统每0.02秒调用一次。
public Transform player;//继承自MonoBehaviour的定义public,接口直接给到unity的面板上
private Vector3 offset;
void Start()
{
//初始化找到摄像机 偏移向量Offset(玩家-相机 = 相机指向玩家的向量)
if (player == null) {
player = GameObject.FindGameObjectWithTag("Player").transform;
}
offset = player.position - transform.position;
}
void Update()
{
//时刻保持这种关系
transform.position = player.position - offset;
}
}
1.1.3.2 摄像机的拉近拉远
设定目标:定义一个Player的Transform
偏移向量Offset
摄像机的位置=(玩家的位置与偏移值的矢量关系)
定义一个距离float distance
通过u3d预定义的滚轮输入轴操作distance的值
再给distance限定范围
private Vector3 offset; //偏移向量Offset
private float speed = 0.1f;//相机渐进
private float distance; //距离
private float scrollSpeed=8;//相机拉近拉远的速度
private void FixedUpdate()
{
ZoomView();
}
void ZoomView()//默认是私有函数
{
distance = offset.magnitude;//获得向量的模 标量
distance += Input.GetAxis("Mouse ScrollWheel")* -scrollSpeed;//负值才会跟滚轮同方向
distance = Mathf.Clamp(distance,5,13); //限制值
offset = distance * offset.normalized; //向量的单位向量*标量=向量
}
通过改变摄像机的广角也能拉近拉远
1.1.3.3 摄像机的旋转
写在鼠标右键内部
查找apitransform.RotateAround
实现水平方向的旋转,带入上述api实现围绕自身y轴旋转
实现垂直方向的旋转,限定一个范围,围绕x轴
通过欧拉角进行x值判定,超过的值改为现在记录的值
更新偏移向量
1.1.4 CharacterController 角色控制器
1.1.5 GameObject 游戏物体
查找物体,组件
//查找物体
GameObject cube=GameObject.Find("路径");
GameObject cube=GameObject.FIndWithTag("标签");
//查找组件
using UnityEngine.UI
GameObject cube=GameObject.Find("路径");
cube.GameObject.GetComponent<Text>().text="gotit";
激活和关闭 物体,组件
GameObject cube=GameObject.Find("路径");
cube.SetActive(true);
cube.SetActive(false);
cube.GetComponent<AudioSurce>().enable=false;
this.enable;//关闭自身这个脚本
1.1.6 Input 输入
获取键盘事件
Input.GetKey("a"); //持续按下
Input.GetKeyDown(KeyCode.A); //按下(一次)
Input.GetKeyUp(); //抬起(一次)
获取鼠标事件 012左右中
Input.GetMouseButtonDown(0); //按下
Input.GetMouseButtonUp(1); //抬起
Input.GetMouseButton(2); //持续
物体跟随鼠标移动
bool isDown=false;
void UpDate(){
if(Input.GetMouseDown(0)){isDown=true;}
if(Input.GetMouseUp(0)){isDown=false;}
if(isDown){
GameObject ob=GameObject.Find("路径");
ob.transform.position=Input.mousePosition;
}
}
1.1.7 MonoBehaviour Mono行为
1.1.7.1 MonoBehaviour.Awake 唤醒
脚本运行时第一个执行的方法,且只执行一次
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test2 : MonoBehaviour
{
void Awake()
{
// print("这是我的第一个程序"); MonoBehaviour类可以用
}
// Start is called before the first frame update
void Start()
{
StartCoroutine(WaitForSometime());//激活协程函数,不影响下一句执行
//如果是自定义类就要用 Debug.Log("我是在Awake函数运行后执行的");
}
// Update is called once per frame
void Update()
{
//print("我是每一帧都执行的函数");
}
IEnumerator WaitForSometime() //协程函数 程序可以延迟一段时间在执行,并且不会影响主线程序的执行
{
yield return new WaitForSeconds(2);//等待两秒
print(11);
Destroy(this.gameObject); //删除自身物体
Destroy(this.transform.gameObject); //也是删除自身
}
}
1.1.7.2 GetComponent 继承函数
public class Test2 : MonoBehaviour
{
public Test3 t3;
void Start()
{
//继承自mono的不能用t3 = new Test3();来实例化
t3 = this.GetComponent<Test3>();
t3.MyDestory();
}
// Update is called once per frame
void Update()
{
}
}
public class Test3 : MonoBehaviour
{
public void MyDestory()
{
Destroy(this.gameObject);//删除物体
}
}
1.1.7.3 timer 计时器
public class Test2 : MonoBehaviour
{
public Test3 t3;
public float timer;
void Start()
{
t3 = this.GetComponent<Test3>();
}
void Update()
{
timer += Time.deltaTmie;//每秒递增
if(timer > 4)
{
t3.MyDestory();
//timer = 0;
}
}
}
1.1.8 Physics 物理学
1.1.9 Quaternion 四元数(物体的旋转)效果好,游戏用
transform.Rotate(transform.up*speed* Time.deltaTime);//指定旋转轴旋转 transform.up自身
transform.eulerAngles();//属性面板上的rotation的xyz就是欧拉角,就是这个
transform.rotation();//四元数 旋转角度
四元数
Quaternion.Angle 角
Quaternion.Lerp 插值
Quaternion.Slerp 球形插值
Quaternion.Euler 欧拉角
Quaternion.identity 恒等式旋转(无旋转
1.1.10 Random 随机
1.1.11 Time 时间
1.1.12 Transform 变换
1.1.12.1 Transform.forward 向前
物体的坐标系,不是世界坐标系
//按世界坐标方向(z轴)进行移动
1.1.12.2 Transform.Translate 平移
如果不写坐标系,默认使用自身的
transform.Translate(transform.forward*Time.deltaTime);//按世界坐标方向(z轴)进行移动
transform.Translate(transform.forward*Time.deltaTime,Space.World);//按自己方向(z轴)进行移动 的两种方法
transform.Translate(Vector3.forward*Time.deltaTime,Space.Self);
1.1.12.3 transform面板 位置
是自己的相对坐标,不是世界的绝对坐标
transform.localPosition 自己的相对坐标
transform.position 世界的绝对坐标
1.1.13 Vector3 三维向量
1.1.13.1 Vector3.Angle 角度
1.1.13.2 Vector3.Cross 叉乘
1.1.13.3 Vector3.Distance 距离
1.1.13.4 Vector3.forward 向前
z轴(0,0,1)世界坐标系
1.1.13.5 Vector3.magnitude 长度
offset.magnitude;//获得向量的模 标量
Mathf.Clamp(distance,5,13); //限制值
Mathf.Abs()取绝对值
1.1.13.6 Vector3.Lerp 插值
moba等非第一人称常用相机渐进跟随效果
public Transform player;//继承自MonoBehaviour的定义public,接口直接给到unity的面板上
private Vector3 offset;
private float speed = 0.1f;
void Start()
{
//初始化找到摄像机 偏移向量Offset(玩家-相机 = 相机指向玩家的向量)
if (player == null) {
player = GameObject.FindGameObjectWithTag("Player").transform;
}
offset = player.position - transform.position;
}
void Update()
{
//时刻保持这种关系
//transform.position = player.position - offset;
transform.position = Vector3.Lerp(transform.position,player.position - offset,speed);
}
具体计算得到返回值也就是 a + (b - a) * speed
1.1.14 【纹理贴图】简析(AO, Normal等)
漫反射贴图 diffuse map
主要用作模型的漫反射颜色,也可看作模型基础颜色,物体本来颜色。比如老虎橙色。那表现橙色的贴图就是漫反射贴图。
法线贴图 normal map
用于保存模型各个顶点切线空间下的法线。用于在片元着色器中进行相关计算,比如光照。
一般在模型是高模时导出法线贴图,然后转化成低模,在低模时用之前导出的法线贴图进行采样和计算,既节省了性能,又能达到不错的效果。
法线在切线空间就是切线空间的z轴,保存到贴图的纹素中就是(0,0,1),这个值对应的是蓝色。
在导出时可能要将模型几个顶点的法线合并到一个纹素中,这个合并是通过插值运算出来的,所以大部分都是蓝色(几个顶点的法线相同,比如一个平面内就是相同的),少部分会有颜色变化。
高光贴图 specular map
表现物体对光照反应的材质。当光照到塑料,布料,金属上时,所展现出的高光部分和高光表现不一样。通过高光贴图上的颜色值表现高光强度,值越大高光反射越强。
AO贴图 Ambient Occlusion
在PBR中计算光照时,一般通过采样IBL得到环境光,这个环境光是该点上一个半球上的积分。
但因为自身的之间会有凹凸,凹陷的地方环境光被遮挡,所以看起来不是那么亮,通过AO贴图可调整环境光大小,达到更真实的效果。
环境光贴图,一般越黑亮度越低,受到的环境光越少。
光照贴图 Light Map
实时光照需要消耗大量计算,如果一个物体和光照的位置相对不变,可提前烘焙出光照贴图,在渲染该物体时采样光照贴图计算混合达到“假”的光照效果,节省性能。
环境贴图,天空盒 Cube Map
存储环境光的贴图,由六个贴图组成为正方形的前后左右上下,这个正方形可看作是整个“世界空间”,我们的眼睛在这个正方体里面。
细节贴图 Detail Map
用来展示细节,一般是一张漫反射贴图,多张细节贴图,通过某种需要的方式进行颜色混合。
15.Animation 动画(Legacy、Generic和Humanoid)
Humanoid 人型骨骼系统,可以将max的骨骼转化为unity的骨骼,并且会生成一份avatar,将avatar指定给不同的角色模型。可无视高矮胖瘦的体型差将同一动画分配给每个角色,实现动画通用。
例:
同一个角色换武器就换一套动作,每件武器都有对应的动画,用humanoid这种可以无视体型的通用骨骼;
角色间不需要共用动画,且每个角色程序单独打包,用legacy(旧版)系统,简单省事。
同一款游戏里也可以主角单独打包使用legacy骨骼,其他怪物使用humanoid骨骼共用动画,以实现资源的最优化。
legacy(旧版)用animation ,泛型才能用animator。
1.2 游戏物体运动方法
1.2.1**不带物理碰撞的(多用在子弹,移动特效等)**
不用加刚体
1.通过改变坐标。
public float speed;
void Start(){
speed = 5;
}
void Update(){//改变z方向
transform.position += new Vector3(0,0,speed*Time.deltatime);
}
2.通过使用transform.Translate(Vector3 temp)进行移动
void Update(){
transform.Translate(transform.forward*speed*Time.deltaTime,Space.World);//按自己方向(z轴)进行移动 的两种方法
transform.Translate(Vector3.forward*speed*Time.deltaTime,Space.Self);
//键盘输入控制移动
if(Input.GetKey(KeyCode.W)){
transform.Translate(transform.forward*speed*Time.deltaTime,Space.World);
}
else if(Input.GetKey(KeyCode.S)){
transform.Translate(transform.forward*-speed*Time.deltaTime,Space.World);
}
else if(Input.GetKey(KeyCode.A)){
transform.Translate(transform.right*-speed*Time.deltaTime,Space.World);
}
else if(Input.GetKey(KeyCode.D)){
transform.Translate(transform.right*speed*Time.deltaTime,Space.World);
}
}
1.2.2**带物理碰撞的(人物的移动)**
需要添加刚体
1.通过刚体Rigidbody进行移动,刚体是放在FixedUpdate固定帧渲染的,所以不用乘以时间间隔Time.deltaTime;
或直接设置速度
//固定帧更新
void FixedUpdate(){
//键盘输入控制移动(力)
if (Input.GetKey(KeyCode.W))
{
GetComponent<Rigidbody>().AddForce(transform.forward * speed * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.S))
{
GetComponent<Rigidbody>().AddForce(transform.forward * -speed * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.A))
{
GetComponent<Rigidbody>().AddForce(transform.right * -speed * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.D))
{
GetComponent<Rigidbody>().AddForce(transform.right * speed * Time.deltaTime);
}
}
//速度
if (Input.GetKey(KeyCode.W))
{
GetComponent<Rigidbody>().velocity = transform.forward * speed ;
}
else if (Input.GetKey(KeyCode.S))
{
GetComponent<Rigidbody>().velocity = transform.forward * -speed;
}
else if (Input.GetKey(KeyCode.A))
{
GetComponent<Rigidbody>().velocity = transform.right * -speed ;
}
else if (Input.GetKey(KeyCode.D))
{
GetComponent<Rigidbody>().velocity = transform.right * speed ;
}
2.通过角色控制器CharacterController进行移动
public CharacterController cc;
public float speed;
void Start()
{
speed = 5;
if (cc == null)
{
//获取物体绑定组件 相当于new
cc = this.GetComponent<CharacterController>();
}
}
void FixedUpdate(){
//角色控制器(物体会默认向前移动)带有碰撞检测
cc.SimpleMove(transform.forward*speed*Time.deltaTime);
}
1.3 游戏NGUI插件的使用方法
1.3.1图集的制作
右键图片素材(类型默认,背景透明),选NGUI,Altas Maker添加图集,新键文件夹Altas;
1.3.2图集的制作图片标签的创建
ui层的摄像机专门负责ui层,其他层看不到,所以不会被干扰
NUGUI创建2dUI,点在UI Root上,矩形工具,脚本框要全打开,右键,creat,sprite。
Anchors 锚点:主要用作自适应界面
可点击的UI:右键 attach 添加box collider,然后再添加button script
UI动画:右键 tween
1.3.3功能按钮的创建
要建panel,把UI放到panle上,好修改好处理
Quest
用到最多的表示任务的单词,接任务、做任务、交任务。
参考:EverQuest、DragonQuest以及Wow和之后所有类Wow的RPG中的任务等
玩家从NPC那儿接受来的任务,上到国王下到村民,从杀人越货到种田采药无所不有,共同点也很明显,都是有报酬的,NPC交给玩家任务之后头上顶着的那个大大的question mark,所以quest的关键词是:来自NPC的、有报酬的一份委托
Mission
mission本身就有任务的意思,而且这个任务往往有很强烈的使命感,是故事的主线。
参考:合金弹头的MISSION COMPLETE!,还有空中魂斗罗这个游戏,原名是FinalMission(最终任务)。
你无法从一个路边的NPC那里接到一份mission,因为mission形容的任务是一种包含了主角的使命和命运的任务。
所以mission的关键词是:主线、使命?此乃天命所归也
Task
除非做的是生产、经营类的游戏,否则我估计这玩意大部分情况下都不会在游戏本身的业务逻辑里出现,因为他描述的任务更像是一份被上级分配、布置下来的作业、工作、或者说差事。
参考:玩kof97的时候连招太华丽,画面渲染不过来就会出现taskover字样,还有…任务管理器(TaskManager)?
比如说,安排一个计划任务,呆会干嘛干嘛,或者定时重复干嘛干嘛。再比如,分配一个加载任务、解析任务给某个具体对象去执行,完了回调等等。
1.3.4人物信息面板的创建![请添加图片描述](https://i-blog.csdnimg.cn/blog_migrate/6358d7f9cdc26ec2f5bd7ceaf4ff27ac.png)
1.Panel底下建Container低下建背景;背景底下建头像,id,等级,血条,设置;
2.血条蓝条 增减 百分比:
右键添加box collider;添加progress bar script;背景和前景填上,前景不要固定fixd aspect,type改已平铺,拉progress bar script脚本NGUISlider的value实现血条增减。
右键添加lebel,填写数字,拉到progress bar script脚本NGUISlider的on value change里设置UILable/SetCurrentPercent,时间百分比显示。
最后取消勾选box collder(不然鼠标点击就能拖拽),要先加因为不加这个不让加进度条脚本。
1.3.5装备面板的创建 ![请添加图片描述](https://i-blog.csdnimg.cn/blog_migrate/bbd35919e2136b30fd8db42e622e11f1.png)
挂载在BGSprite上的脚本: