KEY: transform.positon
transform.position = new Vector3(1,2,3);
//or
public Vector3 newposi;
transform.position = newposi;
脚本已附加在某个GameObject上时 transform.position就是该物体的坐标
获取键盘的输入进行操作 因为是在游戏过程中进行操作 所以要放在Update()
函数里
void Update()
{
//if space key press down
// print a message once
if(Input.GetKeyDown(KeyCode.Space)){
Debug.Log("press down space");
}
// if held on key A
// print message every frame
if(Input.GetKey(KeyCode.A)){
Debug.Log("held on A");
}
// if key lift up
// print message once
if(Input.GetKeyUp(KeyCode.B)){
Debug.Log("lift up B");
}
}
x轴或y上移动
KEY:
transform.Translate()
: Moves the transform in the direction andTime.deltaTime
: The completion time in seconds since the last frame (Read Only). Use Time.deltaTime
to move a GameObject in the y direction, at n units per second. Multiply n by Time.deltaTime
and add to the y component.Vector3.right
: Shorthand for writing Vector3(1, 0, 0).Vector3.left
: Shorthand for writing Vector3(-1, 0, 0).Vector3.up
: Shorthand for writing Vector3(0, 1, 0).Vector3.down
: Shorthand for writing Vector3(0, -1, 0).[SerializeField]
: 强制序列化 使成员变量出现在inspector中 public变量默认是序列化的 通常用于private变量Input.GetAxis()
: Returns the value of the virtual axis identified by axisName. 由键盘控制移动 获取方向上坐标 (查看: Edit -> Project Settings -> Input Manager)
[SerializeField] private float _speed = 0.5f;
void Update()
{
transform.Translate(Vector3.right);
//automatically move obj to right, move 1unit per frame
transform.Translate(Vector3.right*Time.deltaTime);
//automatically move obj to right, move 1unit per second, new Veector3(1,0,0)*0.5f*realtime
transform.Translate(Vector3.right*Time.deltaTime*_speed);
//automatically move obj to right, move 1*_speed unit per second
float horizontalInput = Input.GetAxis("Horizontal");
transform.Translate(new Vector3(horizontalInput, 0, 0)*Time.deltaTime*_speed);
//use keyboard to control
float h = 5*Input.GetAxis("Mouse X");
transform.Translate(new Vector3(h, 0, 0)*Time.deltaTime*_speed);
//use mouse to control
}
Update loop run 60 frames per second --> move 60 unit per second
KEY: Box Collider
- Is Trigger: if checked, we can pass through the object; else, it’s a solid object.
- Ridgebody: 刚体。向对象添加刚体组件将使其运动在Unity物理引擎的控制下。即使不添加任何代码,如果还存在正确的Collider组件,则刚体对象将在重力作用下被下拉,并且会对与传入对象的碰撞做出反应。是让物体更自然运动的组件
- onTriggerEnter()
: get info about the object collide with us when a collision occurs.(if we use solid object, use (此处视频讲错了 应该是onTriggerCollision()
OnCollisionEnter()
另外还有区别是传递的参数是Collision类而不是Collider 详情见文档
注意:两个GameObjects必须包含一个Collider组件。必须启用Collider.isTrigger并包含一个刚体。如果两个GameObjects都启用了Collider.isTrigger,则不会发生碰撞。当两个GameObjects都没有刚体组件时,情况相同。
private void OnTriggerEnter(Collider other) {
// Collider other: whatever obj hit
if(other.tag == "Player"){
Destroy(this.gameObject);
// when the obj with script hit by the object with tag "Player",
// destory the obj with script
}
}
场景:smash hit, fps, 贪吃蛇
[补充] cf.onTriggerEnter()
& OnCollisionEnter()
对比实验(x
共同点:相撞的两个物体都需要Collider(Box或者Mesh什么的都可以
onTriggerEnter()
: (A向B移动
OnCollisionEnter()
: (A向B移动
(这节用到GameDevHQ一个自带动画的模型…emmmmm因为付费所以就没用 但是也不妨碍学习 给随便一个cube附加自动移动的脚本就可以检验了
KEY: Pause the Game 场景:smash hit关卡内加减速
Time.timeScale
: The scale at which time passes. This can be used for slow motion effects. When timeScale is 1.0 time passes as fast as realtime. When timeScale
is 0.5 time passes 2x slower than realtime. When timeScale
is set to zero the game is basically paused if all your functions are frame rate independent. // on main camera
void Update()
{
if(Input.GetKeyDown(KeyCode.Space)){
Time.timeScale = 0;
Debug.Log("press on space and stop the sence");
}
if(Input.GetKeyDown(KeyCode.R)){
Time.timeScale = 1;
Debug.Log("press on R and continue the sence");
}
}
一个疑问 timeScale的改变不单单只是附着的相机视角下画面减速(类似倍速看)而是整个场景真实减速???
cube移动脚本将Time.deltaTime*_speed
序列化显示 并且暂停脚本暂停时改为Time.timeScale = 0.25f
可以看到结果如下 说明是整个场景真实减速
然后看了眼官方文档有下面这句话:
Except for
realtimeSinceStartup
andfixedDeltaTime,
timeScale
affects all the time and delta time measuring variables of the Time class.
把Time.deltaTime
改成 Time.fixedDeltaTime
果然不受影响 但是返回的数值都是Time.fixedDeltaTime
的默认值0.22 也就是说_speed的附加影响没有成功 所以要注意FixedUpdate函数或 Update函数中,Time.fixedDeltaTime
将自动返回正确的增量时间(这就是为什么建议使用Time.deltaTime
了
如果降低timeScale
,建议也将Time.fixedDeltaTime
降低相同的量。设置为零时,不会调用 具体还是看官方链接的代码吧
Window ->Package Manager -> Post Processing
For Main Camera, in Inspector, add component Post Processing Layer and we can notice that in option “layers” there shows “Nothing”. Edit Layers, in user layer, add a layer call “Post Processing”. Then edit the option “layers” for Main Camera as “Post Processing” layer.
Create a GameObject called “Post Process Volume”, which will store all Post Processing Effects we want to apply to the scene. Add a component Post Processing Volume. Choose the layer “Post Processing Layer”. Option Is Gobal, if checked, this post processing effects will be applied to entire scene. Option Profile , click New to create effects. We can adjust the Intensity (强度), Threshold(阈值), Diffusion(扩散) and other attributes. 像还有其他的比如配合Color Grading食用可以让场景光效更酷炫 这边就不多提 用于场景处理
KEY: Smoke-Mirror Effect: When a solid object explodes, it breaks into a million pieces. (啊啊啊啊是我最喜欢的环节!!! 破坏破碎效果!!!!玩smash hit的时候就各种惊叹怎么做到的玻璃破碎得那么真实好看
原理:Physics and colliders 我们需要一个完整的solid object 还有一组fractured part(就是好多个碎块但是可以完整拼凑成一个一毛一样的solid object), 在solid object被执行Destory的同时, 这些fractured part形成爆炸飞出效果。对于fractured part,需要添加Rigidbody 组件, 并赋予重力选项(use gravity),再添加 Mesh Collider 使触面是几何映射(box collider是一个方体 而mesh collider是不规则几何图形即物体的样子,记得点选Convex。注意 这边fractured part是以prefabs的形式设置的。 然后看看代码
public class Crate : MonoBehaviour
{
// Start is called before the first frame update
public GameObject fracturedCrate;
public GameObject explosionEffect;
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.Space)){
// before we destory the solid obj, we first instantiate the prefabs
// which is a series of fractured part as children in the same position and same rotation
// and also the explosion effect
Instantiate(explosionEffect, transform.position, Quaternion.identity);
//Instantiate(fracturedCrate, transform.position, Quaternion.identity);
// to let the power of destory more greater
GameObject fractureObj = Instantiate(fracturedCrate, transform.position, Quaternion.identity) as GameObject;
Rigidbody[] allRigidbodies = fractureObj.GetComponentsInChildren<Rigidbody>();
// grab rigidbody from all of the children elements
if(allRigidbodies.Length > 0){
// if we grab rigidbody, write a loop,
// for each rigidbody we give it a invidual force
foreach(var body in allRigidbodies){
body.AddExplosionForce(500, transform.position, 1);
// 500 newtons of force
// 1 explosionRadius: scale of affect other objects
}
}
Destroy(this.gameObject);
}
}
}
emmmm但是这边讲的是爆炸场景效果 smash hit的话是对撞破碎 猜想smash hit也是一个完整的solid obj 和 一组破碎的prefabs 当撞击产生时根据弹珠接触点进行爆炸?
大致模拟了一下
创建一个蓝色的方块就是我们的Player, 因为要撞击嘛 就给他一个Box Collider, 并且给他一个简单的移动脚本(参见前面 Simple Movement(一句话的事
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerMovement : MonoBehaviour
{
[SerializeField] private float _speed = 0.5f;
// Start is called before the first frame update
void Start()
{}
// Update is called once per frame
void Update()
{
transform.Translate(Vector3.right*Time.deltaTime*_speed);
}
}
然后是设置要被撞击的元大方块Solid Cube, 因为要能够产生撞击, 我们也给他一个Box Collider和RigidBody(参考前面Collectible GameObject 但因为我们想要让它安安稳稳的呆在上面 所以不选择use gravity, Is trigger记得打勾不然无法撞击
同时我们设置一组方块组成和SolidCube一样大小的prefab, 也就是后面生成的BigCube(取名无能的我orz 对于每个方块给他们一个Mesh Collider 其实这边给Box Collider也一样 但是要考虑到在以后会遇到里面的碎片是不规则形状的 就还是用Mesh Collider(养成习惯(x 记住要点选convex 是凸的才能产生交集 然后给每个方块RigidBody 在这边就得赋予重力了 因为想要撞击得飞起来
给Solid Cube一个受到撞击爆炸的脚本 当SolidCube被player击中 生成prefabs给prefabs每个部分增加爆炸威力 同时SolidCube消失(参考前面Destructible Crate
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class crash : MonoBehaviour
{
// Start is called before the first frame update
public GameObject fracturedCrate;
private void OnTriggerEnter(Collider other) {
if(other.tag == "Player"){
Debug.Log("hit");
GameObject fractureObj = Instantiate(fracturedCrate, transform.position, Quaternion.identity) as GameObject;
Rigidbody[] allRigidbodies = fractureObj.GetComponentsInChildren<Rigidbody>();
if(allRigidbodies.Length > 0){
foreach(var body in allRigidbodies){
body.AddExplosionForce(500, transform.position, 1);
// 500 newtons of force
// 1 explosionRadius: scale of affect other objects
}
}
Destroy(this.gameObject);
}
}
}
验收成果!(没有弹珠没有玻璃凑合着看(x
但是问题来了 如果把蓝色方块往上方移动 它爆炸的轨迹还是一样的 问题出在body.AddExplosionForce(500, transform.position, 1);
这句, 爆炸中心是这个物体的坐标 我们应该改成 爆炸中心为撞击的点body.AddExplosionForce(500, other.transform.position, 1);
然后就发现了之前没注意的bug… 为啥实例化物体的坐标和之前不一样啊窒息了 而且在做prefabs的时候吧 就发现scale相同大小是不一样的…就很窒息… 这个问题列入待解决