Unity常用的函数和遇到的C#的知识整理

看Unity的视频也有一段时间了,把视频里面遇到的东西稍微记录一下,

这些东西也算是Unity常用的,整理方便日后要用的的时候来搜索查看,

有些东西要用到但是比较少一点,不容易想起,这里记录下。

好记性不如烂笔头,以后会不定期更新。





Invoke("functionName",time)   

功能:在time时间之后执行函数functionName(),这里这句话和functionName()在同一个脚本,至于调用其他脚本的函数好像不可行。

这里引用一篇对比介绍Invoke的文章:点击打开链接


InvokeRepeating("functionName",time,repeatTime)

功能:  在time时间之后执行函数functionName(),之后每repeatingTime时间再次执行functionName();

这里再引用一篇介绍InvokeRepeating的文章:点击打开链接




get和set

功能:get和set是属性特有的两个方法。属性是对字段的封装,是为了程序数据的安全性考虑的。

总的来说,字段有两种操作权限,就是获取和修改,就分别对应的是get和set方法了,可以通过制定get和set方法来限定字段的访问权限。

这里遇见的是用在单例模式的时候,将脚本实例化物体赋值给私有变量,然后通过get、set来访问该脚本类型的变量,

然后调用其中的方法和属性,get、set保证数据安全性。

private int _age;//年龄 字段
public int Age
{
    get 
   {
      return _age;  
   }
   set
   {
       if(_age<0 || _age>150)  _age=null;
       
       else _age=value; 
    transform.Find("Label").GetComponent<UILabel>().text=""+age;
    }     
 }

调用的时候直接.Age就可以了,写了set的函数可以直接赋值Age=?,只写了get就不行。

这里引用一篇易懂的文章:点击打开链接




SendMessage("functionName",parameters)

功能:调用函数

这里引用一篇简单的文章:点击打开链接



Params 

功能:用在函数声明时候放在数组参数声明前面,用以传递不确定个数的同一类参数。

例如,声明时是method(params int i[]);则调用时候可以是mathod(1)、mathod(2,3)、mathod(1,2,3,4)等等。

这里引用一篇言简意赅的文章:点击打开链接




[HideInInspector]

功能:当你希望有些属性在别的类别的脚本里直接访问到,你把它设置为public属性。

但是在脚本编译好后,你又不希望它出现在unity的Inspector面板,可以在

public前面加上这段话。

这里引用一篇相关术语介绍的文章:点击打开链接



找到在Inspector面板中不启用的物体

如图


这样的物体我们也可以直接在代码中找到他。代码如下:

 this.transform.parent.Find("Conatainer");

其中的this是和Container的父物体相同的物体。

比如这个是NGUI的物体,然后他的transform的父物体就是

UIRoot,这种方法可以找到Unity中没有启用的物体的transform,

如果要找GameObject,可以在后面加上后缀.gameobject。



三维世界里物体旋转的几种方法

  • 当你的GameObject使用了RigidBody组件,可以调用RigidBody里面的AngularSpeed属性,来给角速度赋值。FixedUpda和Update帧长不同,FixedUpdate是在固定帧调用的,一般Rigidbody物理位移的操作可以放在FixedUpdate里面。例如: 在Update函数中
       float h = Input.GetAxis("Horizontal");
       rigidbody.angularVelocity = transform.up * h * angularSpeed;
  • 当然RigidBody类还提供了 MoveRotation()方法,直接将物体移动至某个角度,所以当你需要移动的过程的时候要注意传进去的参数了。比如:在Update()中
       float h = Input.GetAxis("Horizontal");
            float v = Input.GetAxis("Vertical");
            GetComponent<Rigidbody>().MoveRotation(Quaternion.Euler(transform.rotation.x + h * speed * Time.deltaTime, 0, transform.rotation.z + v * speed * Time.deltaTime));
  • 使用transform的Rotate()方法,这个很多人应该都知道了,这个方法有六个重载,具体内容可以查看圣典:点击打开链接
  • 使用Vector3.Lerp函数,实现一个有过程的旋转:
    <span style="white-space:pre">	</span>targetVector=targetTransform.position-transform.position;
    
            transform.forward = Vector3.Lerp(transform.forward,targetVector,rotateSpeed*Time.deltaTime);
    	



三维世界里物体移动的几种方法
  • 当你的GameObject使用了RigidBody组件,里面有个方法叫做MovePosition,和MoveRotation一样,直接将物体移动至某一位置,所以传参要注意一下。例如,在Update()中:

float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
GetComponent<Rigidbody>().MovePosition(transform.position + new Vector3(h, 0, v) * speed * Time.deltaTime);

  • Transform.Translate()函数,这个不多说了,最直接常用的函数,将物体向目标点移动
  • 当你的GameObject使用了CharacterController组件,可以调用CharacterController的SimpleMove和Move方法实现移动。下面引用一篇文章可以了解下SimpleMove方法:点击打开链接

三维世界里物体跳跃的几种方法

使用CharacterController的时候,可以在Update或者FixedUpdate中使用其move方法,在必要的时候(比如按下空格键)添加向上的速度,实现跳跃:

  upSpeed = transform.up * jumpSpeed;
 upSpeed.y -= gravity * Time.deltaTime;
 myController.Move((upSpeed + transform.forward)*Time.deltaTime);


transform.TransformDirection

虽然一直搞不清楚这个函数的具体意思,但是我试用过好多次发现他能把世界坐标的z轴转化为自身的z轴。即如果角色想沿着自身的z轴前进而不是世界的z轴,可以使用这个函数。例如:

transform.TransformDirection(new Vector3(0, 0, 1))

这在有时transform.forward不起效果的时候很有用。


如果在脚本里写有Invoke()来调用方法,然后禁用了该脚本,但是该脚本的某些效果并没有停止,请记得在停用脚本的时候调用CancelInvoke,有参无参

就自己判断了。记得自己在这里找bug找了好久...



Unity更改脚本的执行顺序

单击脚本,然后在Inspector面板可以看到有一个Excution Order按钮


点击之后界面如图:


在这里旋转,格子里的数字越小越在上面,代表越先执行。





继承了UIDragDropItem的类的Start()方法如果要重写记得要在重写的Start()方法里面写上base.Start(),否则会调用出错,以后继承了其他功能类如果遇到错误可以尝试此思路。





获得鼠标位置的方法:

在普通世界坐标中,我们获取物体鼠标位置的方法通常是使用

Camera.main.ScreenToWorldPoint(Input.mousePosition);

这个方法,这里获得的三维坐标的z和摄像机相同,而不是0,所以有必要的话要改z坐标。

然后在NGUI中获得鼠标位置的方法,则是通过

 UICamera.currentCamera.ScreenToWorldPoint(Input.mousePosition);
这个方法来获得的



Unity旧版Animation播放结束的判断

在旧版动画中,有时我们需要在前一个动画播放完成后再播放别的动画。

if (!myAnim.isPlaying)
        {
            myAnim.CrossFade(aniName);
        }

可以使用animation.isPalying变量来判断,这里要注意的是该animationClip的WrapMode是Once,如果是Loop

则isPlaying变量不会变化。至于animation的详解可以参看我转载的博客:点击打开链接



查找判断的物体为null,而不能判断子物体或者组件是否为null

我有时需要某物体的transform,我们查找的时候是应该这样:

GameObject gObj=GameObject.FindGameObjectWithTag(GameTags.swordMan) as GameObject;
        if ( gObj!= null)
        {
            player = gObj.transform;
        }
        else
        {
            player = GameObject.FindGameObjectWithTag(GameTags.magician).transform;
        }
而不是这样:

player = GameObject.Find("Swordman").transform;
        if (player == null)
        {
            player = GameObject.Find("Magician").transform;
        }


获取NGUI的鼠标点击及相应信息

NGUI提供了一个方便的方法

void OnPress(bool isPress)
    {
        this.isPress = isPress;
    }
这个方法的isPress代表鼠标是否按下,可以通过这个标志位来在Update

里面做一些操作。

UICamera.LastTouchPosition表示鼠标在UI界面的点击位置,

以NGUI设计界面的Root的左下角为原点。



动态给NGUI按钮添加点击响应事件

EventDelegate NormalAttackEvent = new EventDelegate(this, "OnNormalAttackClick");
GameObject.Find("NormalAttack").GetComponent<UIButton>().onClick.Add(NormalAttackEvent);
给名字叫NormalAttack的游戏物体的按钮组件添加这个脚本的OnNormalAttackClick的函数。


CharacterController的isGrounded属性

CharacterController提供了属性isGrounded以供检测,但是在使用中发现isGrounded总是返回false,个人认为CharacterController的SkinWidth要设置合理,皮肤厚度决定了两个碰撞器可以互相渗入的深度。较大的皮肤厚值度会导致颤抖。小的皮肤厚度值会导致角色被卡住。一个合理的设定是使该值等于半径(Radius)的10%,再小点检测会更准确点,但是不能太小


当在FixedUpdate里面使用CharacterController.Move或者SimpleMove出现卡顿的时候,不妨把相关代码放在Update里面,卡顿现象可能就会得到解决。


在Unity中一些你想要new出来的类一定不要继承monobehaviour,如果忘记了这一点,你会使劲排查你的程序逻辑却排查不出错误,过了猴年马月后才发现一切正常,只是你要new的类继承了monobehaviour,就new不出来了。


  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值