点击空格,人跳障碍 Project-3
public Rigidbody rb;//公有的可以在检查窗口访问,私有的只能在代码中访问
rb = GetComponent<Rigidbody>();//在start中
//获取刚体Rigidbody组件
//相比将rb设为public后,在编辑器中直接拖拽更加稳定,防止拖拽的对象出错不稳定,拖拽之后没赋值成功
//检查器中的属性显示两个单词之间有空格是是为了区分,在代码中没空格
public float jumpForce = 700f;
if (Input.GetKeyDown(KeyCode.Space))//update中,如果按下空格键,返回true
rb.AddForce(Vector3.up*jumpForce,ForceMode.Impulse);//对刚体施加力
//方向*力,瞬时爆发力
private bool isOnGround = true;//一个标识符,true代表在地面上,false代表不在地面上
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space)&&isOnGround)
{
rb.AddForce(Vector3.up*jumpForce,ForceMode.Impulse);//方向*力,瞬时爆发力
isOnGround = false;
}
}
private void OnCollisionEnter(Collision collision)//实现两个物体碰撞 有弹开效果
{
Debug.Log("OnCollisionEnter");//此函数被调用以此,就在控制台打印一次OnCollisionEnter
isOnGround = true;//与地面碰撞 此时将标识符赋值true以便可以再次按空格弹跳
}
private void OnTriggerEnter(Collider other)//实现两个物体碰撞 无弹开效果 ,用此方法需要在检查器中两个中的一个对象中的BoxCollider中的触发器勾选上
{//只是监测碰撞上了 不做处理 不由物理引擎做处理 由自己写代码做处理
Debug.Log("OnTriggerEnter");
}
public float gravityModifer;//在编辑器中可以填数
Physics.gravity*= gravityModifer;//start中,修改重力g
fublic class MoveLeft : MonoBehaviou
{
public float speed = 15f;
private void Update()
{
transform.Translate(Vector3.left *speed*Time.deltaTime);//图片以某一速度匀速往左动
if (tarnsformpostion.postion.x<=-10)
{
transform.postion=new Vector(47,9.5f,4f);//两张图片连一起整体图片的初始位置Vector(47,9.5f,4f),地面最左端位置是-10
}
}
}
public class MoveLeft : MonoBehaviour
{
public float speed = 15f;
private Vector3 startPos;
private void Start()
{
startPos = transform.position;//图片初始位置
}
private void Update()
{
transform.Translate(Vector3.left *speed*Time.deltaTime);
if (!gameObject.CompareTag("Obstacle"))//判断对象标签与Obstacle是不是相等
{
BoxCollider colider = GetComponent<BoxCollider>();//准备通过BoxCollider获取图片对象的大小 size.x即他的长度
if (transform.position.x <= startPos.x - colider.size.x / 2)//初始位置(这里的x是位置)往左移动了图片的一半,一到这个位置就执行if里面的语句
{
transform.position = startPos;
}
}
}
}
public class MoveLeft : MonoBehaviour
{
public float speed = 15f;
private Vector3 startPos;
private void Start()
{
startPos = transform.position;//图片初始位置
}
private void Update()
{
transform.Translate(Vector3.left *speed*Time.deltaTime);
if (!gameObject.CompareTag("Obstacle"))//判断对象标签与Obstacle是不是相等
{//不相等即是背景图片才进行内部代码,到一定位置立刻回到原位置
BoxCollider colider = GetComponent<BoxCollider>();//准备通过BoxCollider获取图片对象的大小 size.x即他的长度
if (transform.position.x <= startPos.x - colider.size.x / 2)//初始位置(这里的x是位置)往左移动了图片的一半,一到这个位置就执行if里面的语句
{
transform.position = startPos;
}
}
}
}
public class SpawnManager : MonoBehaviour
{
public GameObject obstaclePrefab;
private void Start()
{
InvokeRepeating("SpawnObstacle",2f,2f);//定时器,重复发调用,每隔一段时间调用此方法SpawnObstacle,方法,延迟,时间间隔(默认2s)
}
private void Update()
{
}
void SpawnObstacle()
{
Instantiate(obstaclePrefab);//克隆
}
}
?复杂动画使用专业软件做好的,导进Unity用动画器进行管理,简单动画可以用动画进行制作?
?鼠标滚轮前后放大缩小,Alt+鼠标左键可移动整体图,每个小方块都是一个动画片段,橙色的为默认动画(一般第一个动画为默认动画,也可以将其他的设为默认动画)
可以找到方块对应的动画片段进行播放,观看动画片段
被点击的指向线变蓝色右侧Conditions内的显示对参数的控制,左侧参数编写时例如Speed_f(速度 浮点型float),根据右侧Speed_f(0.25)可知当左侧Speed_f对应的值在0-0.25之间则是walk_Static等等,依次靠参数调整状态
private Animator animator;//为获取一个动画器
private void Start()
{
rb = GetComponent<Rigidbody>();//获取刚体Rigidbody组件
//检查器中的属性显示两个单词之间有空格是是为了区分,在代码中没空格,与拖拽的区别是这种更稳定
Physics.gravity*= gravityModifer;//打印重力
animator=GetComponent<Animator>();//为获取一个动画器,<>:泛型,
//GetComponent("Animator")也可以但不规范
animator.SetFloat("Speed_f", 0.8f);//修改Speed_f值使其处于某个过程线范围内处于某种状态
}
Assets下创建一个新的文件夹Animatitons用来存储动画器,在文件夹内创建一个动画器名为Player?
??
选中小人Player在检查器中添加组件Animator,将动画器Player拖拽到控制器处?,控制器下方的Avatar为骨架,必须赋值骨架,否则无法实现动画
双击控制器Player进入如下界面,idle和Run_Static为后拖拽进来的,鼠标选中方块右键建立过度线,左侧参数点击“+”,添加参数(注意类型),Speed为float型,点击过度线右侧检查器中Condition中选择限制参数Speed,中间为大于小于选择(less为小于),最后设置具体数值(例小于0.5)进入idle状态。
退出时间(勾选时,看蓝色时间线,必须等Run_Static执行完再进入idel)未勾选则满足条件直接进入idel
如果参数为Triger(触发器类型),如右下Conditions中的Jump_trig,则无控制条件,直接触发指向的动作?
若想从Run_Static到Running_Jump,则可以参数中添加一个boolea类型Jump(可以是Run_Static到Running_Jump,点击空格按钮小人跳跃时Jump设为true,Running_Jump到Run_Static人与地碰撞函数中Jump设为false)
Assets文件下创建控制器PlayerAnim,将其拖拽给小人的控制器赋值?
双击进入动画器内部,将动画Run、Running_Jump、Death_01拖拽进控制器里,进行连写过渡,Run到Running_Jump(在控制器参数中添加Bool型名为Jump变量,在小人关联的脚本PlayerController中当点击空格需要将Run转换为Running_Jump设Jump为true,当小人跳起再次落地与地碰撞时将设Jump为false),当小人碰到障碍物时会倒下,所以Run和Running_Jump均指向Death_01(参数中添加一个名为Dead类型为Triger,PlayerController中获取与小人碰撞的对象的标签,如果是障碍物标签,则将设置Triger)
public class PlayerController : MonoBehaviour
{
public Rigidbody rb;//公有的可以在检查窗口访问,私有的只能在代码中访问
public float jumpForce = 700f;
public float gravityModifer;
private bool isOnGround = true;//一个标识符,true代表在地面上,false代表不在地面上
private Animator animator;//为获取一个动画器
private void Start()
{
rb = GetComponent<Rigidbody>();//获取刚体Rigidbody组件
//检查器中的属性显示两个单词之间有空格是是为了区分,在代码中没空格,与拖拽的区别是这种更稳定
Physics.gravity*= gravityModifer;//打印重力
animator=GetComponent<Animator>();//为获取一个动画器
animator.SetFloat("Speed_f", 0.8f);//修改Speed_f值使其处于某个过程线范围内处于某种状态
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space)&&isOnGround)
{
rb.AddForce(Vector3.up*jumpForce,ForceMode.Impulse);//方向*力,瞬时爆发力
isOnGround = false;
animator.SetBool("Jump", true);
}
}
private void OnCollisionEnter(Collision collision)//实现两个物体碰撞 有弹开效果
{
//Debug.Log("OnCollisionEnter");//此函数被调用以此,就在控制台打印一次OnCollisionEnter
if (collision.gameObject.CompareTag("Ground"))//获得碰撞上的物体collision的标签
{
isOnGround = true;//与地面碰撞 此时将标识符赋值true以便可以再次按空格弹跳
animator.SetBool("Jump", false);
}
if (collision.gameObject.CompareTag("Obstacle"))
{
animator.SetTrigger("Dead");//Triger类型,直接调用即触发
}
}
1)可以在与预制体关联的脚本中,利用销毁位置进行写代码销毁
2)可以在层级窗口生成多个预制体对象所利用的空对象所关联的脚本中,每次生成对象写代码控制销毁时间
3)可以在与预制体关联的脚本中,利用销毁时间写代码实现
public class MoveLeft : MonoBehaviour
{
public float speed = 15f;
public float leftBound = -15f;
private Vector3 startPos;
private void Start()
{
startPos = transform.position;//图片初始位置
//Invoke("DestroySelf", 3f);//只调用一次
}
private void Update()
{
transform.Translate(Vector3.left *speed*Time.deltaTime);
//if (this.transform.position.x < leftBound)
//{
// Destroy(this.gameObject);
//}
if (!gameObject.CompareTag("Obstacle"))//判断对象标签与Obstacle是不是相等
{
BoxCollider colider = GetComponent<BoxCollider>();//准备通过BoxCollider获取图片对象的大小 size.x即他的长度
if (transform.position.x <= startPos.x - colider.size.x / 2)//初始位置(这里的x是位置)往左移动了图片的一半,一到这个位置就执行if里面的语句
{
transform.position = startPos;
}
}
}
void DestroySelf()
{
Destroy(this.gameObject);
}
}
public class SpawnManager : MonoBehaviour
{
public GameObject obstaclePrefab;//预制体
private void Start()
{
InvokeRepeating("SpawnObstacle",2f,2f);//定时器,重复发调用,每隔一段时间调用此方法SpawnObstacle,方法,延迟,时间间隔(默认2s)
}
private void Update()
{
}
void SpawnObstacle()
{
GameObject obstacle=Instantiate(obstaclePrefab);//克隆
Destroy(obstacle, 3f);//生成预制体时便直接3秒后销毁
}
}
1)若想在MoveLeft(关联给了预制体和背景图片)中引用PlayerController(关联给小人),在MoveLeft中建立一个PlayerController类,若从项目文件中直接将PlayerController脚本拖拽到界面预制体检查器中对应位置,是拖不进去的,若将预制体拖到层级处形成预制体对象,再将脚本托到检查器对应位置也是拖不进去的,因为PlayerController(关联给小人),所以将层级中的Player(小人对象)托给预制体对象对应的检查器中位置,能拖进去,此时复制成功,在预制体对象关联的MoveLeft脚本中可以使用PlayerController里面的东西。
2)MoveLeft中写代码去整个项目中找对象
private PlayerController playerController;
private void Start()
{
startPos = transform.position;//图片初始位置
//Invoke("DestroySelf", 3f);//只调用一次
GameObject player = GameObject.Find("Player");//去整个场景中找Player对象
playerController=player.GetComponent<PlayerController>();//在Player对象中找PlayerController
}
3)?MoveLeft中写代码去整个项目中找PlayerController
playerController = FindAnyObjectByType<PlayerController>();//整个场景中直接找PlayerController
public class SpawnManager : MonoBehaviour
{
public GameObject obstaclePrefab;//预制体
private PlayerController playerController;
private void Start()
{
playerController = FindAnyObjectByType<PlayerController>();//整个场景中直接找PlayerController
InvokeRepeating("SpawnObstacle",2f,2f);//定时器,重复发调用,每隔一段时间调用此方法SpawnObstacle,方法,延迟,时间间隔(默认2s)
}
private void Update()//实时监测
{
if (playerController.gameOver)
{
CancelInvoke("SpawnObstacle");//一旦游戏结束,取消定时器调用函数
}
}
void SpawnObstacle()
{
if (!playerController.gameOver)//但这种情况虽然不会再克隆障碍物了,但依然会此函数依然在不断调用,需取消定时器
{
GameObject obstacle = Instantiate(obstaclePrefab);//克隆
Destroy(obstacle, 3f);//生成预制体时便直接3秒后销毁
}
}
}
public class PlayerController : MonoBehaviour
{
public Rigidbody rb;//公有的可以在检查窗口访问,私有的只能在代码中访问
public float jumpForce = 700f;
public float gravityModifer;
private bool isOnGround = true;//一个标识符,true代表在地面上,false代表不在地面上
private Animator animator;//为获取一个动画器
public bool gameOver;//true游戏结束 false游戏未结束
public ParticleSystem explosionParticle;//爆炸 粒子特效类
private void Start()
{
rb = GetComponent<Rigidbody>();//获取刚体Rigidbody组件
//检查器中的属性显示两个单词之间有空格是是为了区分,在代码中没空格,与拖拽的区别是这种更稳定
Physics.gravity*= gravityModifer;//打印重力
animator=GetComponent<Animator>();//为获取一个动画器
//animator.SetFloat("Speed_f", 0.8f);//修改Speed_f值使其处于某个过程线范围内处于某种状态
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space)&&isOnGround)
{
rb.AddForce(Vector3.up*jumpForce,ForceMode.Impulse);//方向*力,瞬时爆发力
isOnGround = false;
animator.SetBool("Jump", true);
}
}
private void OnCollisionEnter(Collision collision)//实现两个物体碰撞 有弹开效果
{
//Debug.Log("OnCollisionEnter");//此函数被调用以此,就在控制台打印一次OnCollisionEnter
if (collision.gameObject.CompareTag("Ground"))//获得碰撞上的物体collision的标签
{
isOnGround = true;//与地面碰撞 此时将标识符赋值true以便可以再次按空格弹跳
animator.SetBool("Jump", false);
}
if (collision.gameObject.CompareTag("Obstacle"))
{
animator.SetTrigger("Dead");//Triger类型,直接调用即触发
gameOver = true;
ParticleSystem explosion = Instantiate(explosionParticle);//碰撞时产生爆炸特效,实例化对象
explosion.Play();//爆炸动画播放
}
}
在动画结束编写过程中,PlayerController文件中引用两个动画进行控制,奔跑跟随动画应该拖拽Player中的奔跑动画,爆炸动画拖拽文件中的动画
需要再小人对象里添加组件
int a;
print(a);//控制台打印这两种都可以
Debug.Log(a);
//当变量a不赋值时,int型打印0,float型打印0,bool型打印false(看是否界面中检查器变量勾选),string型打印空字符串,GameObject型打印null
去控制台看,有红色叹号,点击其中一个,看下方报错详细信息,下方蓝色部分点击跳转到报错位置?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnManager : MonoBehaviour
{
public GameObject obstaclePrefab;//预制体
private PlayerController playerController;
private void Start()
{
playerController = FindAnyObjectByType<PlayerController>();//整个场景中直接找PlayerController
InvokeRepeating("SpawnObstacle",2f,2f);//定时器,重复发调用,每隔一段时间调用此方法SpawnObstacle,方法,延迟,时间间隔(默认2s)
}
private void Update()//实时监测
{
if (playerController.gameOver)
{
CancelInvoke("SpawnObstacle");//一旦游戏结束,取消定时器调用函数
}
}
void SpawnObstacle()
{
if (!playerController.gameOver)//但这种情况虽然不会再克隆障碍物了,但依然会此函数依然在不断调用,需取消定时器
{
GameObject obstacle = Instantiate(obstaclePrefab);//克隆
Destroy(obstacle, 3f);//生成预制体时便直接3秒后销毁
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MoveLeft : MonoBehaviour
{
public float speed = 15f;
public float leftBound = -15f;
private Vector3 startPos;
// public PlayerController playerController;
private PlayerController playerController;
private void Start()
{
startPos = transform.position;//图片初始位置
//Invoke("DestroySelf", 3f);//只调用一次
//GameObject player = GameObject.Find("Player");//去整个场景中找Player对象
//playerController=player.GetComponent<PlayerController>();//在Player对象中找PlayerController
playerController = FindAnyObjectByType<PlayerController>();//整个场景中直接找PlayerController
}
private void Update()
{
if(playerController.gameOver!=true)//或if(!playerController.gameOver)
{
transform.Translate(Vector3.left * speed * Time.deltaTime);
}
//if (this.transform.position.x < leftBound)
//{
// Destroy(this.gameObject);
//}
if (!gameObject.CompareTag("Obstacle"))//判断对象标签与Obstacle是不是相等
{
BoxCollider colider = GetComponent<BoxCollider>();//准备通过BoxCollider获取图片对象的大小 size.x即他的长度
if (transform.position.x <= startPos.x - colider.size.x / 2)//初始位置(这里的x是位置)往左移动了图片的一半,一到这个位置就执行if里面的语句
{
transform.position = startPos;
}
}
}
void DestroySelf()
{
Destroy(this.gameObject);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public Rigidbody rb;//公有的可以在检查窗口访问,私有的只能在代码中访问
public float jumpForce = 700f;
public float gravityModifer;
private bool isOnGround = true;//一个标识符,true代表在地面上,false代表不在地面上
private Animator animator;//为获取一个动画器
public bool gameOver;//true游戏结束 false游戏未结束
public ParticleSystem explosionParticle;//爆炸 粒子特效类
public ParticleSystem dirtyParticle;//奔跑跟随粒子特效
private AudioSource audioSource;//为获取音乐组件
public AudioClip jumpClip;//跳音乐,从文件拖入
public AudioClip deadClip;
private void Start()
{
rb = GetComponent<Rigidbody>();//获取刚体Rigidbody组件
//检查器中的属性显示两个单词之间有空格是是为了区分,在代码中没空格,与拖拽的区别是这种更稳定
Physics.gravity*= gravityModifer;//打印重力
animator=GetComponent<Animator>();//为获取一个动画器
//animator.SetFloat("Speed_f", 0.8f);//修改Speed_f值使其处于某个过程线范围内处于某种状态
audioSource = GetComponent<AudioSource>();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space)&&isOnGround&&!gameOver)
{
rb.AddForce(Vector3.up*jumpForce,ForceMode.Impulse);//方向*力,瞬时爆发力
isOnGround = false;
animator.SetBool("Jump", true);
audioSource.PlayOneShot(jumpClip);//按下空格跳时才会有跳音乐响起
}
}
private void OnCollisionEnter(Collision collision)//实现两个物体碰撞 有弹开效果
{
//Debug.Log("OnCollisionEnter");//此函数被调用以此,就在控制台打印一次OnCollisionEnter
if (collision.gameObject.CompareTag("Ground"))//获得碰撞上的物体collision的标签
{
isOnGround = true;//与地面碰撞 此时将标识符赋值true以便可以再次按空格弹跳
animator.SetBool("Jump", false);
}
if (collision.gameObject.CompareTag("Obstacle"))
{
animator.SetTrigger("Dead");//Triger类型,直接调用即触发
gameOver = true;
ParticleSystem explosion = Instantiate(explosionParticle);//碰撞时产生爆炸特效,实例化对象
// explosion.Play();//爆炸动画播放
dirtyParticle.Stop();
audioSource.PlayOneShot(deadClip);//碰撞时才会有碰撞音乐响起
}
}
//private void OnTriggerEnter(Collider other)//实现两个物体碰撞 无弹开效果 ,用此方法需要在检查器中两个中的一个对象中的BoxCollider中的触发器勾选上
//{//只是监测碰撞上了 不做处理 不由物理引擎做处理 由自己写代码做处理
// Debug.Log("OnTriggerEnter");
//}
}
?
?
?