unity3d中localunity deltapositionn和worldunity deltapositionn的区别,概念是什么

Posts - 135,
Articles - 0,
Comments - 138
理论是实践的基础,实践又是检验真理的唯一标准!!
20:06 by 糯米粥, ... 阅读,
Transform组件是每个游戏对象必须有的一个组建,因为你创建一个空物体,它也有该组建,因为unity3d是面向组建开发的一款游戏引擎。通过一张图片来看看它的属性
&你可以在通过代码查看这些属性的区别
Debug.Log("position " + transform.position); //世界坐标的位置
Debug.Log("localPosition " + transform.localPosition); //相对于父位置的坐标 即把父物体当作自己的中心
Debug.Log("eulerAngles " + transform.eulerAngles);//世界坐标欧拉?度
Debug.Log("localEulerAngles " + transform.localEulerAngles);//相对于?级的变换的旋转欧拉?度
Debug.Log("localScale " + transform.localScale);//相对于父位置的缩放
Debug.Log("localRotation " + transform.localRotation);//相对于父位置的旋转
Debug.Log("rotation " + transform.rotation);//世界坐标的旋转
上面提到了父位置?那是什么意思呢?
现在创建两个cube 命名为cube1和cube2 把cube2作为cube1的子对象,如图。
可以看到,cube1的坐标(1,0,0) cube2的坐标为(0,0,5)
那么通过transform.localPosition获取cube2的坐标则为(0,0,5)
如果用transform.position获取cube2的坐标则为(1,0,5)
那么写个脚本测试下。写个脚本挂载到cube2上
在脚本的Start方法中如下写
void Start()
Debug.Log("cube2的世界坐标为:" + transform.position);
Debug.Log("cube2的本地坐标为:" + transform.localPosition);
运行后看结果
因为:cube2把父对象(Cube1)当作了自己的的中心。所以是(0,0,5),那它的世界坐标则为(1,0,5),知道了这个position那localRotation也是同样的道理
但有没有注意到。这里的欧拉角(eulerAngles),rotation和Rotate(),都是用于旋转,那他们有什么区别呢。刚开始我也是犯糊涂
Rotate()方法需要一个vector3三维向量,rotation是用四元素旋转(Quaternion)
来看看圣典上面的解释:
&欧拉角(eulerAngles)旋转很好理解。当你改变Transform组建中的 x,y,z的角度。就是改变其欧拉角
现在来看看rotation属性和Rotate()方法之间有什么区别
我认为通过测试是对两者差异的最好理解。
先看Rotate()方法
在场景中创建一个Capsule,写个脚本。代码如下
void Update()
transform.Rotate(Vector3.up
&运行看看效果:
可以看到对象是旋转一直是在累加5,如果你感觉不出来。我这里调试。一帧一帧给你看
然后用旋转同样的角度。测试rotation属性
void Update()
transform.rotation = Quaternion.Euler(Vector3.up
&同样看效果
&从上图可以看出,Capsule旋转到5就不动了。也就是每次旋转都是同样的值,
所以:我的理解是:
Rotate()方法是:旋转多少度。在原有的基础上累加,即旋转了多少角度。又旋转了多少角度,是在原有的基础上在旋转
rotation属性是:旋转到某个角度,就是是在update中每帧都执行(我这里测试是放在了update中)。但每次旋转到的角度动是5,所以是旋转到5度。一直都是
比如你只想让他旋转到多少,用假如想让他一直转,可以用Rotaterotation直接改变了数值,以达到旋转效果Rotate应用一个的旋转角度每秒1度慢慢的旋转物体
当然:rotation()还可以通过插值旋转,
关于插值的理解:4690人阅读
Unity3D(156)
操作transform.localPosition的时候请小心
移动GameObject是非常平常的一件事情,一下代码看起来很简单:
transform.localPosition +=
Vector3 ( 10.0f * Time.deltaTime, 0.0f, 0.0f );
但是小心了,假设上面这个GameObject有一个parent, 并且这个parent GameObject的localScale是(2.0f,2.0f,2.0f)。你的GameObject将会移动20.0个单位/秒。因为该 GameObject的world position等于:
Vector3 offset =
Vector3( my.localPosition.x * parent.lossyScale.x,
my.localPosition.y * parent.lossyScale.y,
my.localPosition.z * parent.lossyScale.z );
Vector3 worldPosition = parent.position + parent.rotation * offset;
换句话说,上面这种直接操作localPosition的方式是在没有考虑scale计算的时候进行的,为了解决这个问题,Unity3D提供了Translate函数,所以正确的做法应该是:
transform.Translate ( 10.0f * Time.deltaTime, 0.0f, 0.0f );
曝出在Inspector的变量同样的也能被Animation View Editor所使用
有时候我们会想用Unity3D自带的Animation View Editor来做一些简单的动画操作。而Animation Editor不仅可以操作Unity3D自身的component,还可以操作我们自定义的MonoBehavior中的各个Property。所以加入 你有个float值需要用曲线操作,你可以简单的将它曝出到成可以serialize的类型,如:
public float foobar = 1.0f;
这样,这个变量不仅会在Inspector中出现,还可以在animation view中进行操作,生成AnimationClip供我们通过AnimationComponent调用。
public class TestCurve : MonoBehaviour {
public float foobar = 0.0f;
IEnumerator Start () {
yield return
WaitForSeconds (2.0f);
animation.Play(&foobar_op&);
InvokeRepeating ( &LogFoobar&, 0.0f, 0.2f );
yield return
WaitForSeconds (animation[&foobar_op&].length);
CancelInvoke (&LogFoobar&);
void LogFoobar () {
Debug.Log(&foobar = & + foobar);
GetComopnent&T& 可以取父类类型
Unity3D 允许我们对MonoBehavior做派生,所以你可能有以下代码:
public class foo : MonoBehaviour {
public class bar : foo {
假设我们现在有A,B两个GameObject, A包含foo, B包含bar, 当我们写
foo comp1 = A.GetComponent&foo&();
bar comp2 = B.GetComponent&bar&();
可以看到comp1, comp2都得到了应得的Component。那如果我们对B的操作改成:
foo comp2 = B.GetComponent&foo&();
答案是comp2还是会返回bar Component并且转换为foo类型。你同样可以用向下转换得到有效变量:
bar comp2_bar = comp2 as bar;
合理利用GetComponent&base_type&()可以让我们设计Component的时候耦合性更低。
Invoke, yield 等函数会受 Time.timeScale 影响
Unity3D提供了一个十分方便的调节时间的函数Time.timeScale。对于初次使用Unity3D的使用者,会误导性的认为Time.timeScale同样可以适用于游戏中的暂停(Pause)和开始(Resume)。所以很多人有习惯写:
Time.timeScale = 0.0f
对于游戏的暂停/开始,是游戏系统设计的一部分,而Time.timeScale不不是用于这个部分的操作。正确的做法应该是搜集需要暂停的脚本或 GameObject,通过设置他们的enabled = false 来停止他们的脚本活动或者通过特定函数来设置这些物件暂停时需要关闭那些操作。
Time.timeScale 更多的是用于游戏中慢镜头的播放等操作,在服务器端主导的游戏中更应该避免此类操作。值得一提的是,Unity3D的许多时间相关的函数都和 timeScale挂钩,而timeScale = 0.0f将使这些函数或动画处于完全停止的状态,这也是为什么它不适合做暂停操作的主要原因。
这里列出受timeScale影响的一些主要函数和Component:
MonoBehaviour.Invoke(…)
MonoBehaviour.InvokeRepeating(…)
yield WaitForSeconds(…)
GameObject.Destroy(…)
Animation Component
Time.time, Time.deltaTime
Coroutine 和 IEnumerator的关系
初写Unity3D C#脚本的时候,我们经常会犯的错误是调用Coroutine函数忘记使用StartCoroutine的方式。如:
TestCoroutine.cs
IEnumerator CoLog () {
yield return
WaitForSeconds (2.0f);
Debug.Log(&hello foobar&);
当我们用以下代码去调用上述函数:
TestCoroutine
testCo = GetComponent&TestCoroutine&();
testCo.CoLog ();
testCo.StartCoroutine ( &CoLog& );
那么testCo.CoLog()的调用将不会起任何作用。
StartCoroutine, InvokeRepeating 和其调用者关联
通常我们只在一份GameObject中去调用StartCoroutine或者InvokeRepeating, 我们写:
StartCoroutine ( Foobar() );
InvokeRepeating ( &Foobar&, 0.0f, 0.1f );
所以如果这个GameObject被disable或者destroy了,这些coroutine和invokes将会被取消。就好比我们手动调用:
StopAllCoroutines ();
CancelInvoke ();
这看上去很美妙,对于AI来说,这就像告诉一个NPC你已经死了,你自己的那些小动作就都听下来吧。
但是注意了,假如这样的代码用在了一个Manager类型的控制AI上,他有可能去控制其他的AI, 也有可能通过Invoke, Coroutine去做一些微线程的操作,这个时候就要明确StartCoroutine或者InvokeRepeating的调用者的设计。讨论之前我 们先要理解,StartCoroutine或InvokeRepeating的调用会在该MonoBehavior中开启一份Thread State, 并将需要操作的函数,变量以及计时器放入这份Stack中通过并在引擎每帧Update的最后,Renderer渲染之前统一做处理。所以如果这个
MonoBehavior被Destroy了,那么这份Thread State也就随之消失,那么所有他存储的调用也就失效了。
如果有两份GameObject A和B, 他们互相知道对方,假如A中通过StartCoroutine或InvokeRepeating去调用B的函数从而控制B,这个时候Thread State是存放在A里,当A被disable或者destroy了,这些可能需要一段时间的控制函数也就失效了,这个时候B明明还没死,也不会动了。更 好的做法是让在A的函数中通过B.StartCoroutine ( … ) 让这份Thread State存放于B中。
// class TestCortouine
public class TestCoroutine : MonoBehaviour {
public IEnumerator CoLog ( string _name ) {
Debug.Log(_name + & hello foobar 01&);
yield return
WaitForSeconds (2.0f);
Debug.Log(_name + & hello foobar 02&);
// component attached on GameObject A
public class A: MonoBehaviour {
public GameObject B;
void Start () {
TestCoroutine
compB = B.GetComponent&TestCoroutine&();
// GOOD, thread state in B
// same as: compB.StartCoroutine ( &CoLog&, &B& );
compB.StartCoroutine ( compB.CoLog(&B&) );
// BAD, thread state in A
StartCoroutine ( compB.CoLog(&A&) );
Debug.Log(&Bye bye A, we'll miss you&);
Destroy(gameObject); // T_T I don't want to die...
以上代码,得到的结果将会是:
B hello foobar 01
A hello foobar 01
Bye bye A, we'll miss you
B hello foobar 02
如不需要Start, Update, LateUpdate函数,请去掉他们
当你的脚本里没有任何Start, Update, LateUpdate函数的时候,Unity3D将不会将它们加入到他的Update List中,有利于脚本整体效率的提升。
我们可以从这两个脚本中看到区别:
Update_01.cs
public class Update_01 : MonoBehaviour {
void Start () {}
void Update () {}
Update_02.cs
public class Update_02 : MonoBehaviour {
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:823911次
积分:9243
积分:9243
排名:第1244名
原创:78篇
转载:350篇
评论:69条
(2)(3)(2)(1)(3)(1)(4)(2)(2)(6)(25)(2)(5)(3)(65)(20)(2)(4)(4)(58)(12)(10)(82)(75)(25)(1)(1)(1)(3)(2)(8)(1)Version: 5.3 ()
LanguageEnglish
Script language
Select your preferred scripting language. All code snippets will be displayed in this language.
Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable.
Sumbission failed
For some reason your suggested change could not be submitted. Please try again in a few minutes. And thank you for taking the time to help us improve the quality of Unity Documentation.
Your email
Suggestion *
Submit suggestion
var localPosition: ;
localPosition;
Description
Position of the transform relative to the parent transform.
If the transform has no parent, it is the same as Transform.position.
// Move the object to the same position as the parent:
transform.localPosition = (0, 0, 0);
// Get the y component of the position relative to the parent
// and print it to the Console
print(transform.localPosition.y);
using UnityE
using System.Cpublic class ExampleClass :
void Example() {
transform.localPosition = new (0, 0, 0);
print(transform.localPosition.y);
Note that the parent transform's world rotation and scale are applied to the local position when calculating the world position.
This means that while 1 unit in Transform.position is always 1 unit, 1 unit in Transform.localPosition will get scaled by the scale of all ancestors.查看: 1767|回复: 1
精华11在线时间165 小时帖子主题UID70053积分22825技术分8970 资源分1146 分享激情5848 博客好友记录相册
UID70053积分22825
移动GameObject是非常平常的一件事情,一下代码看起来很简单:
transform.localPosition += new Vector3 ( 10.0f * Time.deltaTime, 0.0f, 0.0f );
但是小心了,假设上面这个GameObject有一个parent, 并且这个parent GameObject的localScale是(2.0f,2.0f,2.0f)。你的GameObject将会移动20.0个单位/秒。因为该 GameObject的world position等于:
Vector3 offset = new Vector3( my.localPosition.x * parent.lossyScale.x,
& && && && && && && && && && &my.localPosition.y * parent.lossyScale.y,
& && && && && && && && && && &my.localPosition.z * parent.lossyScale.z );
Vector3 worldPosition = parent.position + parent.rotation *
换句话说,上面这种直接操作localPosition的方式是在没有考虑scale计算的时候进行的,为了解决这个问题,Unity3D提供了Translate函数,所以正确的做法应该是:
transform.Translate ( 10.0f * Time.deltaTime, 0.0f, 0.0f );
精华67在线时间17387 小时帖子主题UID1积分403452技术分133285 资源分20093 分享激情125976 博客好友记录相册
首席研究员
UID1积分403452
thanks for sharing
人生是一种修行
一级王者勋章
一级王者勋章
DEVDIV博主
及时将最新信息发给我
通过Email及时将最新的模板和服务发给我。
及时了解我们最新动态。关注我们的微博
官方微博: &&&6481人阅读
Unity3D(8)
一&World&Space(世界坐标):
我们在场景中添加物体(如:Cube),他们都是以世界坐标显示在场景中的。transform.position可以获得该位置坐标。
1. 代码获取的transform.position都是一致的
无论是3d还是2d,ugui/ngui,父子关系,transform.position都是以场景中心(0,0)的位置开始计算,单位长度也都是一样的。
x轴:左负右正
y轴:上正下负
z轴:里正外负
无论怎样的UI,怎样的层级关系,代码里输出Debug.log(go.transform.position),输出的总是相对于场景中心(0,0)的距离,也是获取世界坐标的方法。
2. 检视面板的position数值和代码获取的position数值不一致
ngui和ugui的Transform和Recttransform的position显示的数值和代码里获取的transform.position不一致。
ugui btn代码位置position=new Vector(1,0,0),面板显示(31.3,0,0)
ngui btn代码位置position=new Vector(1,0,0),面板显示(371,0,0)
具体比例不是很清楚,可能和测试环境有关。
3. 父子关系的容器,检视面板position和代码获取position不一致
cube和ngui/ugui的子对象的Transform/Recttansform在检视面板中显示的Position数值是相对于父容器的,
但是代码里获取的Transform/RectTransfrom的position是相对于场景中心的。
获取世界坐标:go.transform.position
获取本地坐标:go.tranfrom.localPosition & (cube/ngui/ugui,无论层级关系,都是获取的是检视面板中的坐标)
可推断ugui/ngui都是在场景中的一个容器之中,所以检视面板显示的都是相对于父容器的坐标,而不是世界坐标。
二 Screen&Space(屏幕坐标):
以像素来定义的,以屏幕的左下角为(0,0)点,右上角为(Screen.width,Screen.height),Z的位置是以相机的世界单位来衡量的。
鼠标位置Input.mousePosition获取的是屏幕坐标。
例如场景分辨率,如果屏幕被缩小至100x100,那么点击右上角是100x100,而不是分辨率的。
三 ViewPort&Space(视口坐标)
视口坐标是标准的和相对于相机的。相机的左下角为(0,0)点,右上角为(1,1)点,Z的位置是以相机的世界单位来衡量的。
四 绘制GUI界面的坐标系:
这个坐标系与屏幕坐标系相似,不同的是该坐标系以屏幕的左上角为(0,0)点,右下角为(Screen.width,Screen.height)。
坐标转换:
世界坐标 -& 本地坐标:貌似不用转,直接可以position和localPosition获取。
本地坐标 -& 世界坐标:
世界坐标→屏幕坐标:camera.WorldToScreenPoint(transform.position);这样可以将世界坐标转换为屏幕坐标。其中camera为场景中的camera对象。
屏幕坐标→视口坐标:camera.ScreenToViewportPoint(Input.GetTouch(0).position);这样可以将屏幕坐标转换为视口坐标。其中camera为场景中的camera对象。
视口坐标→屏幕坐标:camera.ViewportToScreenPoint();
&视口坐标→世界坐标:camera.ViewportToWorldPoint();
父子对象关系:
SetParent(Transform parent, bool worldPositionStays);
false:不保留世界坐标。改变层级关系后,坐标数值不变,位置变化,会相对于父对象移动。
true(默认):世界坐标不变。改变层级关系后,不会移动。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
(4)(12)(5)(2)(1)(3)(24)(70)

我要回帖

更多关于 local position 的文章

 

随机推荐