Unity 3D 5.0版本以上用C#rhino5.0英文语言包如何编写退出游戏按钮的代码?

游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)
说起状态模式游戏开发者们第一个想到的一定是AI的有限状态机FSMs,状态模式确实是实现有限状态机的一种方法。之后还会讲状态机的进阶分层状态机(hierarchical state machines),和pushdown自动机(pushdown automata), 本文就拿人物控制的有限状态机来讲讲状态机模式,本文例子其实是状态模式和观察者模式的组合,通过获取玩家按键消息来改变状态。
如果不使用有限状态机
如果想要你实现一个2d或3d游戏中的人物控制(本文拿2d游戏举例),可以让人物走、跑,相信不少人会这么写:
if (Input.GetKey(KeyCode.D))
&设置方向向右..
if (Input.GetKey(KeyCode.LeftShift))
..移动..播放跑步动画..
..移动..播放走路动画..
else if (Input.GetKey(KeyCode.A))
&设置方向向左..
if (Input.GetKey(KeyCode.LeftShift))
..移动..播放跑步动画..
..移动..播放走路动画..
然后再加上跳跃功能,怎么办呢,跳跃时肯定不能执行走路的操作播放走路的动画啊,加一个bool判断吧,然后代码变成了这样:
bool isJump =
if (Input.GetKeyDown(KeyCode.W))
if (Input.GetKey(KeyCode.D))
&设置方向向右..
if (Input.GetKey(KeyCode.LeftShift))
if(!isJump)
..移动..播放跑步动画..
..移动..播放跳跃动画..
if(!isJump)
..移动..播放走路动画..
..移动..播放跳跃动画..
else if (Input.GetKey(KeyCode.A))
&设置方向向左..
if(!isJump)
..移动..播放跑步动画..
..移动..播放跳跃动画..
if(!isJump)
..移动..播放走路动画..
..移动..播放跳跃动画..
然后我们又希望人物按D键能够实现蹲走,怎么办,再加一个bool,再加判断!
bool isCrouch =
if (Input.GetKeyDown(KeyCode.S))
isCrouch =
bool isJump =
if (Input.GetKeyDown(KeyCode.W)&&! isCrouch)
if (Input.GetKey(KeyCode.D))
&设置方向向右..
if (Input.GetKey(KeyCode.LeftShift))
if(!isJump&&! isCrouch)
..移动..播放跑步动画..
else if(!isCrouch)
..移动..播放跳跃动画..
..移动..播放蹲走动画..
if(!isJump&&! isCrouch)
..移动..播放跑步动画..
else if(!isCrouch)
..移动..播放跳跃动画..
..移动..播放蹲走动画..
else if (Input.GetKey(KeyCode.A))
&设置方向向左..
if(!isJump&&! isCrouch)
..移动..播放跑步动画..
else if(!isCrouch)
..移动..播放跳跃动画..
..移动..播放蹲走动画..
if(!isJump&&! isCrouch)
..移动..播放跑步动画..
else if(!isCrouch)
..移动..播放跳跃动画..
..移动..播放蹲走动画..
然后再加入攻击,跳劈,潜袭,站防,蹲防,还要再继续添加if else 和bool吗?我们究竟能容忍多少这样纠缠在一起的的ifelse? 稍有不慎会出多少错误?调试起来复杂不?。。。这种方法显然是错误的!有大量复杂的分支,极易出现bug。不过,救星来了,就是有限状态机
一个最简单的有限状态机
阿兰图灵提出的图灵机就是一种状态机,就是指一个抽象的机器,它有一条无限长的纸带TAPE,纸带分成了一个一个的小方格,每个方格有不同的颜色。有一个读写头HEAD在纸带上移来移去。机器头有 一组内部状态,还有一些固定的程序。在每个时刻,机器头都要从当前纸带上读入一个方格信息,然后结合自己的内部状态查找程序表,根据程序输出信息到纸带方格上,并转换自己的内部状态,然后进行移动。
状态机需要满足的条件:
1. 一组固定的状态(空闲,行走,跳跃,攻击。。。)
2. 状态机一次只能处在一种状态,最简单的例子,我们不能跳的同时蹲下。
3. 一些玩家输入或者事件发送到状态机,来改变现有状态
4. 状态与状态之间的转换都有一个过渡,在这个过渡中不接受玩家的任何输入,比如从站立到蹲下的过渡中玩家在此时按下跳跃或行走等是没有响应的(被忽略)。
根据上面的条件,我们在写一个状态机之前必须要做的一件事就是&画状态图,这样既可以理清你的思路,方便添加状态与功能,又能使你的遗漏减少。
比如我们想实现一个人的走、跑、跳、攻击、防御,状态图可以这么画:
enum&switch
然后我们完成最精简的状态机,就是enum和switch的组合。
我们需要把一组状态放在enum里,命名就按你需要的状态的名字来命名,比如空闲-idle,还需要一个变量来储存当前控制人物的状态:
public enum CharacterState
Idling = 0,
Walking = 1,
Jumping = 2,
acting= 3,
defending= 4,
public CharacterState
heroState = CharacterState. I
设置一个函数handleInput来专门处理判断玩家的输入与状态操作,把这个函数放在update中每帧轮询。
void handleInput()
switch(heroState)
case CharacterState. Idling:
&播放空闲动画..
if&Input.GetKey &A,D.
this. heroState = CharacterState. W
else if&Input.GetKey &w.
this. heroState = CharacterState. J
else if&Input.GetKey &J.
this. heroState = CharacterState.
else if&Input.GetKey &I.
this. heroState = CharacterState.
case CharacterState. Walking:
if&Input.GetKey &A,D.
&CharacterController移动操作..
else&Input.GetKeyUp & A,D&
this. heroState = CharacterState. I
case CharacterState. Jumping:
if(Input.GetKeyUp(KeyCode.W))
&CharacterController移动操作..
if(CharacterController.isGrounded)
this. heroState = CharacterState. I
case CharacterState. acting:
&播放攻击动画.
chargeTime += Time.timeScale / Time.deltaT
if(chargeTime&maxTime)
this. heroState = CharacterState. I
chargeTime = 0;
case CharacterState. defending:
&播放防御动画.
if(Input.GetKeyUp(KeyCode.I))
this. heroState = CharacterState. I
这里又需要通过时间来转换状态的,比如攻击状态,我们按下攻击键,执行一个攻击动画,当动画结束时,我们希望人物能回到空闲状态,此时就需要一个chargeTime变量来记录攻击状态持续了多长时间,在每一帧chargeTime加上这一帧的运行时间,也就是这个动画现在播放了多久,我们获取动画总时间长度来作为maxTime,当chargeTime达到maxTime也就是说明一个攻击动作做完了(一个动画播完了)就会转换到空闲状态,在转换到空间状态时再重置chargeTime为0。
这样可以实现一个简单的状态机,所有状态操作都被整合在一起,原理是轮询当前的状态,处理当前状态操作,接受玩家输入来转换状态。
此时这样一个状态机会出现一个问题,我们控制的人物不能跳起来时不能攻击,而且状态机规定一次只能处在一种状态,所以解决办法为拆分成几个状态机,比如负责移动的为一个状态机,攻击防御为另一个状态机,这两个状态机并发运行,就可以实现跳起攻击,或者潜袭等操作了。
当然,这样的状态机有很多缺点,比如不方便添加新状态,这个函数最终也会越写越长越乱。一种好的实现方式就是把每一个状态和它的操作还有在这个状态时对用户输入的判断,也就是对这一个状态的所有处理都封装在一个类中,这就是状态模式。
在实现状态模式之前,让我们先来了解一下的委托与事件。
c#的委托与事件
说起委托与事件,就肯定与观察者模式挂钩了。
delegate委托就是可以用这个委托调用别的类中的一个或多个函数
event事件通常与委托联用,就是事件发送者,通过委托调用事件接收者中的函数,来发送事件到事件接收者
在有限状态机中,我们的发送者是update中的按键,接收者就是等待处理按键的状态对象(后面会讲)。在update中判断玩家输入,再把输入的按键作为事件发送给状态对象处理。就是这么一个过程。
此处就拿攻击方面状态举例
首先我们先写一个EventArgs事件数据类的子类,是事件要传送的消息,也就是我们的接收者-状态对象想要接收的消息,这个消息可以自己定义,在此处,我们希望传送按键信息在接受者中处理
using UnityE
using System.C
public class InputEventArgs : EventArgs
public string addition1;
public string addition2;
public InputEventArgs(string _input, string _addition1, string _addition2)
this.input = _
this.addition1 = _addition1;
this.addition2 = _addition2;
类中的参数用来存储信息此处的input为按键,addition1,addition2,留空,以便以后开发需要新的信息。作为攻击方面状态addition1,addition2可以是武器的种类(不同的攻击方式,不同的播放动画,不同的技能等等)也可以对组合键加以判断(有些游戏中组合键可以让人物发出某些特殊技能)
然后来看看事件发送者,新建一个hero类专门控制人物状态操作,heroStateActVer储存着当前状态,在update函数中
public delegate void InputEventHandler(object sender, InputEventArgs e);
public event InputEventHandler InputT
InputEventArgs inputArgs = new InputEventArgs(,,);
State heroStateActV
void Start()
personCtrl = this.GetComponent();
heroStateActVer = new IdleStateActVer(this.gameObject);
InputTran += new InputEventHandler(heroStateActVer.handleInput);
void Input_events(InputEventArgs e)
if (e != null)
InputTran(this, e);
void Update()
if (Input.anyKeyDown)
foreach (char c in Input.inputString)
if (c != null)
inputArgs.input = c.ToString();
Input_events(inputArgs);
heroStateActVer.UpDate();
state的UpDate()存储了对该状态的实时操作,heroStateActVer.UpDate();为处理当前状态该有的操作,比如行走状态就是CharacterController.move,之后我们会讲解
我们在发送类中定义委托与事件,我们接收用户按键,以字符串的形式存储在事件信息类InputEventArgs中把它发给接受者state对象
我们之所以使用foreach,是因为Input.inputString可以接收多个按键,比如A键和D键同时按,Input.inputString就是&ad&,如下图所示,所以我们遍历一帧按下的所有键,来发送消息。
然后就是我们的接收类,也是订阅者state,state对象中有一个方法用来接收发送者发来的事件信息,也就是当事件发生时执行的函数
public void handleInput(object sender, InputEventArgs e)
input = e.
switch (input)
case j://攻击
&转为攻击状态..
case i://防御
&转为防御状态&
四人帮说:
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.
当一个对象的状态改变时来改变他的行为。对象将会改变它的类。
继承于父类状态的各个子状态其中的每一个把它的操作还有在这个状态时对用户输入和外部事件的判断,也就是对这一个状态的所有处理都封装在一个类中,对用户输入的判断和外部事件进行处理,如果需要则改变对象的状态。
在这个类中,我们需要,接受事件的方法handleInput(),实时处理当前状态操作的(如move状态就是处理人物移动)Update(),注意我们并没有继承于 MonoBehaviour,所以这里的Update()不是继承于MonoBehaviour的,是我们自己定义的,之后要放在人物发送类中的MonoBehaviour的Update()中执行 。进入状态时的操作Start(),退出状态时的操作Exit()(根据需要可加可不加)
首先我们需要定义一个父类State,让各种状态都继承于他,我们保存人物发送类和操作类的对象,便于在状态中update()里对人物的控制。chargeTime上面讲过,就是一个状态的持续时间。
using UnityE
using System.C
public class State
protected GameObject P
protected Hero Person_
protected float chargeT
protected float MaxT
public State(GameObject _Person)
this.Person = _P
this.Person_ctrl = _Person.GetComponent();
public virtual void handleInput(object sender, InputEventArgs e)
public virtual void UpDate()
public virtual void UpDate()
public virtual void Start()
Start()函数是在上一个状态结束,开始下一个状态时调用的函数,之调用一次,UpDate()是要放在人物发送类中的UpDate()中实时运行,handleInput在玩家输入按键时被调用处理,负责转换状态,我们把该状态中对应的所有按键的判断放在里面。
然后在来看看子类攻击状态
using UnityE
using System.C
public class ActState : State
public ActState(GameObject _Person)
: base(_Person)
public override void Start()
this.chargeTime = 0.0f;
this.MaxTime =..攻击动画时间..
..播放攻击动画..
public override void handleInput(object sender, InputEventArgs e)
input = e.
switch (input)
case j://连击
if (chargeTime & MaxTime - 0.1f)
Person_ctrl.GetActState(1).Start();
case i: //转换为防御状态
if (chargeTime & MaxTime - 0.1f)
Person_ctrl.SetActState(2);
Person_ctrl.GetNowActState().Start();
public override void UpDate()
if (chargeTime & MaxTime)
chargeTime += Time.timeScale / Time.deltaT
this.chargeTime = 0.0f;
Person_ctrl.SetActState(0);
Person_ctrl.GetNowActState().Start();
可以看到,在start函数中也就是状态开始,刷新chargeTime,播放攻击动画,在update函数中,更新时间chargeTime,判断是否超过指定时间MaxTime(此处为一次攻击动画时间),如果超过则切换当前状态为空闲,handleInput接收事件输入,object sender是事件发送者,就是例子中的Hero类, InputEventArgs e是传入的按键信息,在该函数中判断是否需要转换状态,或者作出相应操作。所以,状态转换是在我们封装的状态对象中实现的。
我们有两种方法获取状态对象。一种是定义一个状态类,把状态声明为静态来获取, 不需要消耗内存来实例化,想要攻击状态就AllState. actState就可以,:
using UnityE
using System.C
public class AllState
public static State actState = new ActState();
public static State jumpState = new JumpState();
但是这种方法并不能两个人物共用,状态时间chargeTime是无法公用的,这个问题很关键,所以,还有一种就是在Hero类里实例化状态对象,可以实现多任务共用状态,因为在每个人物类里都有状态的实例。
private State[] hero_act_state = new State[3];
hero_act_state[0] = new IdleStateActVer(this.gameObject);
hero_act_state[1] = new ActState(this.gameObject);
hero_act_state[2] = new DefenseState(this.gameObject);
然后再写一个get,set方法,使状态变量更加安全,这里不做代码示范了。
在有限状态机中,一般都是观察者模式与状态模式连用,状态模式把每个状态封装成类,来对每个输入消息(按键)处理,完全摆脱了大量if else的纠缠,减轻了大量逻辑错误出现的可能,但是本身也有很多缺点,因为状态毕竟是有限的,,当状态少的时候可以运用自如,当状态多的时候10个以上就已经结构非常复杂,而且容易出错,之前在游戏人工智能开发之6种决策方法 提到如果用在AI上会产生一些问题,所以之后会发文讲状态机的进阶-分层有限状态机。
本来是写状态模式的,所以不得不提有限状态机,有限状态机当然要包括观察者模式了,所以写本篇的时候思路有些混乱,委托和事件也只是稍微提了一下。。如果有错误,或者是建议请评论或私信。
部分代码已共享至github
命令模式:游戏开发设计模式之命令模式(unity3d 示例实现)
对象池模式:游戏开发设计模式之对象池模式(unity3d 示例实现)
原型模式:游戏开发设计模式之原型模式 & unity3d JSON的使用(unity3d 示例实现)
博主近期渲染:最近用unity5弄的一些渲染扫一扫,访问微社区
后使用快捷导航没有帐号?
签到成功!您今天第{todayrank}个签到,签到排名竞争激烈,记得每天都来签到哦!已连续签到:{constant}天,累计签到:{days}天
关注:1165
当前位置: &
查看: 2430|回复: 3
Unity3D开发之常用笔记
本帖为抢楼帖,欢迎抢楼!&
89845/10000排名<font color="#FF昨日变化2主题帖子积分
常驻蛮牛, 积分 9845, 距离下一级还需 155 积分
常驻蛮牛, 积分 9845, 距离下一级还需 155 积分
蛮牛币178491
在线时间432 小时
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
才可以下载或查看,没有帐号?
  1.动画倒放 .speed *= -1.0;
  2.寻找场景中物体var door = GameObject.Find(“door”).
  3.全局变量用法,A.js 里的 static var AAA 到 B.js 里调用方式为 A.AAA
  4.function Awake() 创建一个物体时自动运行的程序
  5.js 中可以使用 “” +&&0 将数字转换为字符串
  6.3d字体较为模糊是因为使用了anti-aliasing,可以创建大的字体物体,将字体属性中的 size 设为小一些来解决
  7.InvokeRepeating(函数名, 开始执行函数的时间, 调用函数的间隔时间);和 Update() 差不多但可以间隔着时间执行
  8.Quaternion.Slerp(起点,目标点,期间耗费时间)
  9.解决轴心,用物体绑定到 Empty GameObject 之下
  10.隐藏鼠标 Screen.showCursor =
  11.FixedUpdate()以指定频率被调用。
  可以在 Edit -& project settings -& Time -& Fixed Timestep 中设定该频率。
  12.计算圆半径 wheel.tireGraphic.renderer.bounds.size.y / 2;
  13.显示载入关卡的进度条
  var levelToLoad = 1;
  function LoadNewLevel () {
  if (Application.CanStreamedLevelBeLoaded (levelToLoad)) {
  Application.LoadLevel (levelToLoad);
  如果想在播放器中显示下载进度,可以通过GetStreamProgressForLevel()函数来读取进
  14.用灯光中的 cookie 选项可以模拟移动的云的阴影
  15.模拟爆炸伤害
  使用 Component-&Particle-&World Particle Collider 添加一个粒子碰撞物体
  如果 Send Collision Message 被启用, 任何发生碰撞的粒子都会发送一个
  OnParticleCollision()到粒子系统附加的物体和与粒子发生碰撞的物体上。
  调用 OnDrawGizmosSelected () 或者 OnDrawGizmos() 函数
  16.function Update () {
  if (Input.GetButtonDown (“Jump”)) {
  if (renderer.material.mainTexture.isPlaying) {
  renderer.material.mainTexture.Pause();
  else {
  renderer.material.mainTexture.Play();
  17.function Start () {
  yield WaitForSeconds(3);
  print(“hello”);
  18.容器菜单里的选项随着导入工程而变化
  19.把物体直接层级面板拖动到工程面板就是Prefab了
  @script AddComponentMenu(“Universol Conraller/Cube Controller”) //把容器添加进菜单栏
  @script RequireComponent(Llight)&&在物体中加入某个容器
  21.Camera.main可以得到相机
  22.Collider 必须搭配 Rigidbody 来使用,就像 Rigidbody 必须搭配 GameObject 一样
  23.RigidBody 中的 IsKinematic 勾选后就不受物理控制了,没有重力了,但加了碰撞的Rigidbody物体还是会接收碰撞,但只能该物体碰撞它物体,如果受到它物体的碰撞不会发生反应,但触发器能接收信号,一般 IsKinematic 物体在完全受用户控制而不受其他物体影响时使用
  宜于勾选的物体
  赛车、子弹、人物、地形等
  不宜勾选的物体
  可被撞倒的路边垃圾桶、足球等
  RigidBody 中的 Continuous/Continuous Dynamic 可以让运动物体碰撞静止物体时产生触碰信号
  RigidBody 中的 sleepVelocity 可以忽略最小的运动来停止
  24.Reset() 替换,用于设置物体的默认值也可以用
  25.几个物体只要一个激活了其他就不能被调用的情况可以用设置 Static 物体来处理
  26.iphone的常亮:iPhoneSettings.screenCanDarken =
  Good organization is important if you want your workflow to be smooth and hassle
  Use instantiated Prefabs wherever possible.
  Try organizing by function instead of type.
  Use Empty GameObjects as containers.
  28.音效来源Apple's own Garage Band, Logic Studio 8 and Soundtrack / Soundtrack Pro software
  29.CollisionFlags 可判断出碰撞物体的方向
  30.Camera 容器的 Depth 参数可以调整几个摄像机的层级关系
  31.为什么这里要用 SendMessage();playerLink.GetComponent(ThirdPersonController).SendMessage(“HidePlayer”);
  32.LOD(Level-of-detail 编辑器)
  33.QualitySettings.currentLevel = QualityLevel.F
  34.ctrl + shift + n 新建 Empty GameObject
  35.BeginGroup + EndGroup 可以创建一个类似 window 的区域,同时进行移动操作
  36.导入文件时勾选 Generate Colliders 选项会自动为物体加入 MeshCollider 碰撞体
  37.如何查看场景是否已经完成预加载,显示进度条功能
  function Start() {
  var async : AsyncOperation = Application.LoadLevelAsync(“Game”);
  Debug.log(“Loading Complete”);
  function OnGUI() {
  //显示进度条
  GUI.Label(Rect(100,300,200,200),(Application.GetStreamProgressForLevel(1) * 100.ToString(), “%”);;
  //如果已经预加载完毕,则点击 Start 进入场景
  if(GUI.Button(Rect(100,100,200,100), “Start”)){
  if(Application.CanStreamedLevelBeLoaded(1)) {
  Application.LoadLevel(“Game”);
  另外WWW.Progress 可以检测下载进度(0~1)
  EditorUtility.DisplayProgressBar 可以显示进度条
  38.Unity 下载 OGG 音乐
  public class DAudio: MonoBehaviour
  string url = “http://XXXXXXXXXXXXXXXXXXXXXXXX.ogg”;
  WWW myWWW;
  AudioC
  IEnumerator WWWLoading()
  myWWW = new WWW(url);
  yield return myWWW;
  ac = myWWW.audioC
  void Start()
  StartCoroutine(WWWLoading());
  void OnGUI()
  if (myWWW.isDone)
  audio.clip =
  39.Unity API 坏了,搜索 API 时看似搜到了结果,但一条结果都未显示
  上网下载 index.js覆盖原有的 index.js
  40.各种常用数学函数
  Mathf.CeilToInt: 根据小数取整,如果该数不是整数,就加一个正的小数让他变成整数
  Mathf.FloorCeilToInt: 根据小数取整,如果该数不是整数,就减一个正的小数让他变成整数
  Mathf.RoundToInt: 根据小数取整数,四舍六入,如果小数是 0.5,则根据当前整数位取偶数整数
  41.判断是否下载完毕
  使用 myWWW.isDone 或者 myWWW.progress == 1f&&来判断
  尤其注意判断条件要写在 OnGUI() 里,不能写在 Update() 里,否则判断结果会有误差
  42.如何在多个脚本中控制每个 Start 函数调用的先后顺序
  在一个主 Start() 函数中依次调用各个脚本的初始化函数
  使用全局静态变量,当前一个脚本中的相应初始化函数模块初始化完毕后,改变全局静态变量值来通知下一个脚本开始初始化。
  43.自定义函数继承 Transform 或 GameObject 的方法
  严格的来说是不行的,一般只能使用将自定义类作为 Component 绑定到物体上的方法,该物体可以是新建的 GameObject 或者克隆出的物体皆可
  44.用 VS2010 打开项目文件失败,如下提示:
  Couldn't call method SyncVisualStudioProject because the class SyncVS couldn't be found.
  UnityEditor.DockArea:OnGUI()
  解决方法:在 Unity 中,改变项目中的该脚本的位置(拖至其他文件夹下或最顶层),不要放在文件夹里打开,此时即可用 VS 打开,然后如果再拖回先前的文件夹后,也依然能打开
  45.GUI 图片按中心进行旋转或缩放
  RotateAroundPivot(float angle, Vector2 pivotPoint)
  ScaleAroundPivot(Vector2 scale, Vector2 pivotPoint)
  46.if 语句尽量使用大括号,否则容易出现让人摸不着头脑的错误
  比如:
  if(false)
  Debug.Log(“AAA”);
  Debug.Log(“BBB”);
  print(“CCC”);
  由于Debug最终不输出,结果就被编译成了
  if(false) {
  print(“CCC”);
  47. 查看自身能否看着目标物体(目标物体是否在背后)
  Vector3 dir = (target.position - transform.position).
  float direction = Vector3.Dot(dir, transform.forward);
  48.如何建立不受父亲物体影响的位置移动
  Transform.TransformDirection(Vector3 direction)
  Transform.Translate(Vector3 direction, Space.World)
  49.通过脚本控制物体的几种方法
  1) 通过 GameObject.Find(“物体名字”) 保存该物体,然后就可随意对其控制了
  2) 脚本中设置 public transform 物体,脚本给其他物体后,在外部把相应物体拖入
  3) 直接给该物体,脚本中直接使用 transform 来控制
  50.参照某一点缩放整个 GUI 的方法
  GUIUtility.ScaleAroundPivot (Vector2 scale, Vector2 pivotPoint);
  51.截屏的方法
  T& && && && &&&//截图生成的图片
  //最终获取图像大小
  tex = new Texture2D((int)texMax.z, (int)texMax.w, TextureFormat.RGB24, false);
  //截取屏幕的区域
  tex.ReadPixels(new Rect(texMax.x, texMax.y, texMax.z, texMax.w), 0, 0);
  //接受大小修改
  tex.Apply();
  52.动态缩小图片的方式
  GUI.DrawTexture(new Rect(shotPngX, camRect.y, shotPngWidth, camRect.height), tex, ScaleMode.StretchToFill, true);
  53.计算匀速数字变化
  height = Mathf.Lerp(height, 10f, flightSpeed * Time.deltaTime / (10f - height));
  54.如何锁定轴向运动
  Component && Physics && Configurable Joint
  55.在视图中按下 Ctrl + F,可以快速输入要查找的物体名字来定位物体
  56.如何显示局部 GUI 界面
  通过 GUI.Window() 作为窗口物体
  57.相机剔除,也就是选择相机所看到的层
  camera.cullingMask = 1 && LayerMask.NameToLayer(“LayerName”);
  或者camera.cullingMask = Mathf.Pow(2, LayerMask.NameToLayer(“LayerName”))
  前一种效率更高,后一种让代码更易读
  想添加多个剔除的话可以用
  camera.cullingMask = 1 && LayerMask.NameToLayer(“LayerName1”);
  camera.cullingMask += 1 && LayerMask.NameToLayer(“LayerName2”);
  …………
  58.鼠标经过按钮提示文字标签功能
  GUI.Button(newRect(10, 10, 100, 20), newGUIContent(“Click me”, “This is the tooltip”));
  GUI.Label(newRect(10, 40, 100, 40), GUI.tooltip);
  59.焦点改变事件
  curFocus = GUI.SetNextControlName(“name”);
  name = GUI.TextField(nameRect, name);
  GUI.GetNameOfFocusedControl();
  注:Button不能记录 Focus 事件,需要手动记录
  例如:
  if(GUI.Button(ApplyRect, “OK”))
  curFocus = “OK”;
  1.GUI 的插件:iGUI、UIToolKit
  2.地形插件:TerrainToolkit
  模型类型
  .FBX, .dae, .3DS, .dxf .obj
  图片类型
  PSD, TIFF, JPG, TGA, PNG, GIF, BMP, IFF, PICT
unity button 隐藏;unity按钮点击判断; 5.0 32位下载;uunity3d 伤害数字;unity加载外部图片;unity 动态显示文字;unity 锁定鼠标;unity invokerepeating 停止;uquunity粒子爆炸;vs unity3d 插件;unity3d锁;unity 隐藏unity判断点击按钮;unity3d下载32位;unity3d 32位下载;uunity3d 弹出伤害数字;unity 外部加载图片;显示动态文字unity鼠标锁定;unity怎么锁定鼠标;unity 停止unity invokerepeating 限制;iununity 爆炸粒子;unity3d中的vs插件;unity3d怎么锁定z轴;unity 5.0鼠标隐藏;unity如何隐藏鼠标;类似unity 纯音乐;类似unity 音乐;类似于unity的音乐;unity类似的音乐;unity加载场景进度条;unity锁定旋转;多个字体替换ac unity什么意思;ac unity怎么开始
每日推荐:
我是一朵内心长满小碎花的女汉子!
5963/1000排名<font color="#FF昨日变化1主题帖子积分
熟悉之中, 积分 963, 距离下一级还需 37 积分
熟悉之中, 积分 963, 距离下一级还需 37 积分
蛮牛币2867
在线时间190 小时
赞一个&&就是在分类明确点就好了
每日推荐:
123/50排名<font color="#FF昨日变化28主题帖子积分
注册看看, 积分 23, 距离下一级还需 27 积分
注册看看, 积分 23, 距离下一级还需 27 积分
在线时间6 小时
心是好心啊,但,这样新来的人,看不清啊。
每日推荐:
4466/500排名<font color="#FF昨日变化1主题帖子积分
四处流浪, 积分 466, 距离下一级还需 34 积分
四处流浪, 积分 466, 距离下一级还需 34 积分
在线时间109 小时
bucuo de dongxi++++++++++++_++++++++++++++++++++++++++++++++
每日推荐:
社区QQ达人
使用QQ帐号登录论坛的用户
游戏蛮牛QQ群会员
加入游戏蛮牛官方QQ群
在“新人报到 ”版块发过自己的照片
购买游戏蛮牛书籍

我要回帖

更多关于 c语言规范5.0中文版 的文章

 

随机推荐