为bilibili教程【【Unity教程】零基础带你从小白到超神】 https://www.bilibili.com/video/BV1gQ4y1e7SS/?p=50&share_source=copy_web&vd_source=6e7a3cbb802eb986578ad26fae1eeaab的笔记
1、灯光的使用
定向光模拟太阳,是平行光。旋转定向光,光线角度会变化
阴影类型:无阴影/硬阴影(性能消耗小)/软阴影(性能消耗大)
剪影:类似选择太阳光斑,选择什么图片,就投射怎样的阴影形状
剔除遮罩:选择是否为某一layer物体打光,例如可以不用给ui层物体打光
聚光相当于一个手电筒
点光源相当于一个灯泡,注意灯光光线也会衰减,要照亮可以增加强度或者扩大照射面积
以上三种灯光都有模式可以选择 混合/实时/已烘焙。混合 = 实时+ 烘焙。实时为游戏中实时计算的灯光,耗性能。烘焙指预先计算的,不会在运行中变化的信息。贴上烘焙灯光信息贴图之后,可以将不需要的灯光源删除
区域(仅烘焙),从平面发射出来的平行光,是面光。(烘焙把游戏纹理和光照计算一遍,然后保存下来,等用的时候直接调用,不需要玩家的设备实时去算 优化性能用的- 弹幕云)
烘焙方法:窗口-》渲染-》生成照明
可以看到,将灯光删除之后,烘焙的灯光信息依旧表现
2、相机
相机的“深度”值越高,越优先显示。当游戏物体中有两个相机时,可更改深度来更改显示优先级
清除标志一般是将两个相机所拍摄物体相容(fps持枪视角枪身看起来永远不穿模就是这么做的-弹幕)。例如相机main 清除标志-天空盒,相机 addicitive 清除标志 -- 仅深度。可以通过清除标志仅深度+深度优先级来使多个相机的内容一起显示
可实现功能 游戏ui或者比赛场地/演播室/观众席三个画面同框(弹幕)、小地图(弹幕)
fov轴和视野搭配使用。剪裁平面的远、近是指相机的近平面和远平面
viewport矩形里面的值x,y,w,h是比例。x,y代表从界面的百分之几开始,w,h则代表表示的画面宽高。可以用于实现画中画或者双人成行的分屏显示或者玩具熊的午夜后宫中的监控器显示
目标纹理配置之后,目标显示就会被替代。并且渲染器纹理可以拉到游戏物体上,可以用来实现游戏玩家在游戏里的电视机上看到自己被监控的画面,3d停车场游戏中的后视镜画面(弹幕),实现在游戏里玩游戏
3、音频
增加audio source组件
唤醒时播放 - 程序运行时自动播放
音频的最小声音和最大声音可以结合起来做脚步声和收音机的音效
public class AudioTest : MonoBehaviour
{
//AudioClip
public AudioClip music;
public AudioClip se;
//播放器组件
private AudioSource player;
// Start is called before the first frame update
void Start()
{
player = GetComponent<AudioSource>();
//设定播放的音频片段
player.clip = music;
//循环
player.loop = true;
//音量
player.volume = 0.5f;
//播放
player.Play();
}
// Update is called once per frame
void Update()
{
//按空格切换声音的播放和暂停
if(Input.GetKeyDown(KeyCode.Space))
{
//如果当前正在播放声音
if (player.isPlaying)
{
//停止播放
player.Pause();
//player.Stop();
}
else
{
//继续
player.UnPause();
//开始播放
//player.Play();
}
}
//按鼠标左键播放声音
if (Input.GetMouseButtonDown(0))
{
player.PlayOneShot(se);
}
}
}
4、视频
可以通过vedioplayer组件+渲染器纹理播放. plane+渲染器纹理播放可实现游戏中的广告大屏播放效果
或者ui ->原始图像,通过纹理播放
public class vediotest : MonoBehaviour
{
private VideoPlayer player;
// Start is called before the first frame update
void Start()
{
player = GetComponent<VideoPlayer>();
}
// Update is called once per frame
void Update()
{
}
}
5、角色控制器的使用
public class Playercontrol : MonoBehaviour
{
private CharacterController player;
// Start is called before the first frame update
void Start()
{
player = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
//水平轴
float horizontal = Input.GetAxis("Horizontal");
//垂直轴
float vertical = Input.GetAxis("Vertical");
//创建成一个方向向量
Vector3 dir = new Vector3(horizontal,0, vertical);
Debug.DrawRay(transform.position, dir, Color.red);
//朝向该方向移动
player.SimpleMove(dir);
}
}
6、重力
添加rigidbody刚体组件。阻力是运动时受到的阻力,角阻力是旋转时受到的阻力。碰撞检测选择离散的,可能会导致物体没有检测到它们互相进行了碰撞。可以选择地面持续检测,子弹连续动态。“是运动学的”勾选之后,物体不再受物理规律影响。冻结位置可以使物体在某一轴向上不移动
7、检测碰撞
碰撞半径是绿色的线框
public class FireTest : MonoBehaviour
{
//创建一个爆炸预设体
public GameObject prefab;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
//监听发生碰撞
private void OnCollisionEnter(Collision collision)
{
//创建一个爆炸物体
Instantiate(prefab,transform.position,Quaternion.identity);
//销毁自身
Destroy(gameObject);
//获取碰撞到的物体
Debug.Log(collision.gameObject.name);
}
//持续碰撞中
private void OnCollisionStay(Collision collision)
{
}
//结束碰撞
private void OnCollisionExit(Collision collision)
{
}
}
public class Expositest : MonoBehaviour
{
float timer = 0;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
timer += Time.deltaTime;
if(timer >=1)
{
Destroy(gameObject);
}
}
}
//销毁爆炸效果,销毁脚本应搭载在爆炸效果预制件上,而不是火焰效果预制件上
8、触发
让相机与场景视野保持一致 :选中相机,游戏对象-》对齐视图
触发与碰撞区别:碰撞是两个物体都有碰撞属性,触发是一个物体有碰撞属性,另一个物体有触发属性
public class cubecontrol : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
//碰撞获取的是发生碰撞的信息体
private void OnCollisionEnter(Collision collision)
{
}
//参数是进入触发的碰撞器
private void OnTriggerEnter(Collider other)
{
GameObject door = GameObject.Find("DOOR");
if (door != null) {
door.SetActive(false);
}
}
private void OnTriggerStay(Collider other)
{
}
private void OnTriggerExit(Collider other)
{
}
}
9、物理关节
例如:门与墙之间的连接合页(物理关节)
hinge joint组件中anchor的数值是按比例算的 物体原点算000,修改anchor可修改joint位置。修改“轴”可修改joint的朝向
要使门变成自动门,可以使用motor,给与一个初始力和速度
运动学刚体是指不受外力或碰撞影响的刚体。它不会受到物理引擎的模拟,而是通过直接设置位置和旋转来控制其运动。这意味着你可以手动控制运动学刚体的位置和旋转,而不会受到物理引擎的影响。(弹幕)
spring joint ,弹簧组件。不动的物体要设置为运动学的
固定关节组件,fixed joint,类似于胶水作用,可设置断开力矩,受到超过这个力的时候,两个物体会分离
10、物理材质
摩擦组合是指两个附有物理材质的物体接触后,他们之间的摩擦力该如何计算。例如冰和地面间的摩擦力。而反弹合并,指两个都有反弹力的物体间接触后,它们间的弹力该如何组合
11、射线检测
要把相机的tag改为Main camera。
多检测效果--比如FPS一发子弹可能打中两个人,两个人都掉血;比如说穿透子弹的效果;比如地面上有一块被伞或树挡住,单检测碰到树叶就停下了,玩家无法就走到树下面(弹幕)
public class RayTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
//方式一
//Ray ray = new Ray(Vector3.zero, Vector3.up);
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
//方式2 按下鼠标左键发射射线
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//申明一个碰撞信息类
RaycastHit hit;
//碰撞检测
bool res = Physics.Raycast(ray, out hit);
//如果碰撞到的情况下,hit就有内容了
if (res == true)
{
Debug.Log(hit.point);
transform.position = hit.point;
}
//多检测,参数可以有检测距离,只检测某一图层
//RaycastHit[] hits = Physics.RaycastAll(ray,100,1<<10);
}
}
}
//实现鼠标点到哪,物体移动到哪
12、粒子系统的基本应用
"预热“--去除掉粒子系统成长的从无到有的第一个周期
”模拟空间“-- 局部,生成的粒子还跟随父物体的移动而移动。而世界,是生成的物体不跟随父物体的移动而移动,只有即将生成的粒子会受移动的影响
13、线段渲染器
线段渲染器(line render组件)所画出的图形,会随着旋转视角的改变而展示更全面.可以用于战旗游戏的移动路径(弹幕)。
public class LineTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
//设定线段的位置
//获取线段渲染器
LineRenderer lineRenderer = GetComponent<LineRenderer>();
lineRenderer.positionCount = 3;
lineRenderer.SetPosition(0, Vector3.zero);
lineRenderer.SetPosition(0, Vector3.one);
lineRenderer.SetPosition(0, Vector3.down);
}
// Update is called once per frame
void Update()
{
}
}
此部分代码与位置功能相同
运行后
可以用拖尾(trail render)实现(飞船的引擎拖尾,挥剑时的刀光)。游戏中物体移动时生成拖尾
自动销毁-- 拖尾完成后,挂载拖尾渲染器的物体会跟随一起消失
可实现水果忍者类似的效果
14、动画
animations组件(旧版动画组件),culling type优化方式
窗口-》动画—》动画,打开动画面板
可以通过动画窗口的添加属性按钮,添加组件的属性进行k帧;或者通过录制按钮进行录制。
可以对动画资产选择贴图拼接属性
在动画窗口还可以选择曲线来可视化动画关键帧的位置变化
public class AnimationTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
GetComponent<Animation>().Play("right");
}
}
}
animator组件(新版)和动画器控制器组合使用,并且新版的动画和旧版的动画属性也不一致
public class AnimatorTest : MonoBehaviour
{
private Animator animator;
// Start is called before the first frame update
void Start()
{
//获取动画器组件
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
animator.Play("down");
}
}
}
//按下鼠标左键播放动画改变
15、动画间的过渡
动画间的过渡和ue的动画状态机差不多,用各种参数和函数控制触发
public class PlayControllerTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.F))
{
//触发pickup参数
GetComponent<Animator>().SetTrigger("pickup");
}
}
}
但这个代码会发现按F之后会有延迟才执行pickup,这是因为有退出时间(动作后摇,魂游所爱),可以取消勾选退出时间来取消后摇
16、人物的移动及播放动画
public class PlayerMoveController : MonoBehaviour
{
private Animator animator;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
//水平轴
float horizontal = Input.GetAxis("Horizontal");
//垂直轴
float vertical = Input.GetAxis("Vertical");
//向量
Vector3 dir = new Vector3(horizontal,0, vertical);
//当用户按下方向键
if (dir != Vector3.zero)
{
//面向向量
transform.rotation = Quaternion.LookRotation(dir);
//播放跑步动画
animator.SetBool("isRun", true);
//朝向前方移动
transform.Translate(Vector3.forward * 2 * Time.deltaTime);
}
else {
//播放站立动画
animator.SetBool("isRun", false);
}
}
}
如果还觉得有过渡的效果不好,可以将过渡持续时间改为0,但是这样会导致动作切换的生硬。适当的过渡有更好的演出效果
17、剪辑的常用设置
rig中如果为旧版,就要选用animation组件(旧版组件)
循环匹配为动画的第一帧和最后一帧是否能顺利流畅的匹配起来,也就是循环时前一周期的最后一帧和这一周期的第一帧连起来时看起来不会有很大的突兀。循环匹配为黄色时代表第一帧和最后一帧不能顺利流畅的匹配
根变换旋转、根变换位置等查看其他资料或者查看这套教程lesson49
18、曲线和帧事件
曲线可以在动画中添加设置,在脚本中被使用。使用场景可以是蓄力拳,随按键时间的增加,在某一时刻用获取到的数值来判断特效的放出效果强弱
而帧事件可以实现诸如人物在水面上脚落地时的涟漪,左脚落地时产生火花效果,左右脚落地时产生脚步音效,或者fps游戏时换弹时每次都弹出弹壳,打枪时也会弹出弹壳
public class PlayerMoveController : MonoBehaviour
{
private Animator animator;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
//水平轴
float horizontal = Input.GetAxis("Horizontal");
//垂直轴
float vertical = Input.GetAxis("Vertical");
//向量
Vector3 dir = new Vector3(horizontal,0, vertical);
//当用户按下方向键
if (dir != Vector3.zero)
{
//面向向量
transform.rotation = Quaternion.LookRotation(dir);
//播放跑步动画
animator.SetBool("isRun", true);
//朝向前方移动
transform.Translate(Vector3.forward * 2 * Time.deltaTime);
}
else {
//播放站立动画
animator.SetBool("isRun", false);
}
//随时获取test参数并打印出来
//Debug.Log(animator.GetFloat("Test"));
}
void leftfoot()
{
//可以在这边播放音效或者添加特效
Debug.Log("左脚");
}
void rightfoot()
{
Debug.Log("右脚");
}
}
19、混合动画(混合状态)
跟虚幻的混合空间相同,自然的形成不同动画间的过渡,例如从走到跑
automate thresholds取消勾选和勾选能改变threshold的值
blend tree还可以套娃
20、动画层
any state状态,是指无论任何状态,都能通过某一条件转为跑步状态。例如,人物有一百多个动画,就可以通过只创建这一个过渡而不是创建一百多条过渡条件过渡到跑步。
状态机中还可以创建子状态机,实现嵌套。例如,可以拿刀的的动画全放在一类状态机里,拿枪的动画可以放在另一类子状态机中。分类,方便整理,不用创建多个动画器控制器(弹幕)
21、动画分层
动画分层如果不搭配遮罩使用,会变成平移着挥手,脚不动这种情况
但搭配遮罩,就可以根据骨骼ik来选择播放哪一层动画.上面动画分类可以是新增子状态机,但也可以是通过动画分层来实现的,例如将拿枪的放到一层,拿刀的放到另一层,这样可以通过脚本改变权重,来改变播放动画