- Home /
Converting script from JS to C#
This snippet of code is from the BootCamp demo's SoldierController.js Update() where it tries to turn the character based on camera movement changes.
JS:
soldierTransform.localRotation.eulerAngles.y = Mathf.MoveTowards(currentAngle, currentAngle + delta, Time.deltaTime * maxRotationSpeed);
C#: (FAIL)
soldierTransform.localRotation.eulerAngles += new Vector3(0.0f,Mathf.MoveTowards(currentAngle, currentAngle + delta, Time.deltaTime * maxRotationSpeed),0.0f);
Error: Cannot modify the return value of 'UnityEngine.Transform.localRotation' because it is not a variable.
So I understand this thread: http://forum.unity3d.com/threads/6404-Cannot-modify-....-because-it-is-not-a-variable-in-C
But this is sort of a nested example -- modifying a Quaternion.Vector3 -- and I don't know how to get around this one. Anyone able to explain? Better yet, what would be a clean readable way to do this operation?
Answer by Bunny83 · Jan 05, 2013 at 02:23 AM
Well, who wrote that script has a really bad style of programming. I'm actually even wondering that it works in UnityScript.
What you want are the localEulerAngles.
soldierTransform.localEulerAngles = soldierTransform.localEulerAngles + new Vector3(0.0f, Mathf.MoveTowards(currentAngle, currentAngle + delta, Time.deltaTime * maxRotationSpeed), 0.0f);
To understand what was wrong here's a quick explanation:
Whenever you put a dot behind a class or struct you read / access the reference.
So just the very first part of your line
soldierTransform.localRotation
will read / use what ever is before the dot in this case the reference stored in soldierTransform.
localRotation is a property of the Transform class. A property is just syntactical sugar for a get and set method. So when ever you read a property the getter is called. When you assign something to the property the setter is called. The big problem are properties of value types like structs (Vector3, Quaternion). If the getter is called it will return a copy of the object. It can't return a reference since it's a value type.
Now take a look at the next part of your line:
soldierTransform.localRotation.eulerAngles
Again because of the dot behind localRotation you will read localRotation. Since it's a property you will access a copy of the Quaternion. What ever you do with the eulerAngles property of the quaternion (read or write) will be done on the copy.
soldierTransform.localRotation.eulerAngles += XXX
The += operator is the same as
soldierTransform.localRotation.eulerAngles = soldierTransform.localRotation.eulerAngles + XXX;
So in the end you assign a new value to the eulerAngles property of a temporary copy of the localRotation Quaternion. This will effectively do nothing because the temporary copy will be lost after that operation. You never invoked the setter of localRotation to assign a new Quaternion.
In UnityScript the compiler automatically creates temp variables, read the current value, store them locally, do the changes and assign them back to the property .
soldierTransform.localRotation.eulerAngles += new Vector3(0.0f,Mathf.MoveTowards(currentAngle, currentAngle + delta, Time.deltaTime * maxRotationSpeed),0.0f);
Here's a nice example i've just tried. This line of UnityScript:
// UnityScript
transform.localRotation.eulerAngles.y = 5.0;
will translate to this actual code:
// C#
float y = 5f;
Quaternion localRotation = this.transform.localRotation;
Vector3 eulerAngles = localRotation.eulerAngles;
float num = eulerAngles.y = y;
Vector3 vector = localRotation.eulerAngles = eulerAngles;
Quaternion quaternion = this.transform.localRotation = localRotation;
I just put this line of UnityScript into a project, built an standalone player and opened the Assembly-UnityScript.dll with ILSpy and let it decompile to C#
Thank you! This is why javascript is a dangerous language to be scripting with. At least with C#, you know what you are getting. It's too bad so many of the tech demos use js, thus the community does too.
@marnes: Well, in the end it's about the same. You just have to know what you get when you do something. UnityScript is less strict but might produce some overhead you wouldn't expect. C# on the other hand might cause more frustration for people new to coding since the compiler would bash you until you have it right ;).
I wouldn't say that C# is the better language. If you really know UnityScript in all it's colors you can produce the same quality code you can with C# but UnityScript tend to produce a little bit overhead. I guess a major part is that the UnityScript compiler uses the Boo compiler to produce the .NET / $$anonymous$$ono assemblies, so it probably produces some kind of intermediate code for the Boo compiler.
Answer by DaveA · Jan 05, 2013 at 01:24 AM
From that post you linked to, I would guess:
soldierTransform.localRotation.eulerAngles = soldierTransform.localRotation.eulerAngles + new Vector3(0.0f,Mathf.MoveTowards(currentAngle, currentAngle + delta, Time.deltaTime * maxRotationSpeed),0.0f);
If that also causes a problem, you can try:
Vector3 soldierAngles = soldierTransform.localRotation.eulerAngles;
soldierAngles += new Vector3(0.0f,$$anonymous$$athf.$$anonymous$$oveTowards(currentAngle, currentAngle + delta, Time.deltaTime * maxRotationSpeed),0.0f);
soldierTransform.localRotation.eulerAngles = soldierAngles;
@$$anonymous$$ovich: That won't work either ;) see my answer
@Bunny83: Nice catch. I wasn't aware that Quaternions were a struct too.
Answer by Imankit · Jan 05, 2013 at 10:28 AM
soldierTransform.localRotation.eulerAngles = new Vector3(soldierTransform.localRotation.eulerAngles.x,Mathf.MoveTowards(currentAngle, currentAngle + delta, Time.deltaTime * maxRotationSpeed),soldierTransform.localRotation.eulerAngles.z);
This will definitely work...
No, this won't work since localRotation returns a copy of a valuetype. Unity even throws an error:
error CS1612: Cannot modify a value type return value of `UnityEngine.Transform.localRotation'. Consider storing the value in a temporary variable
It will work in UnityScript because the compiler does the temp-var caching behind the scenes. See the last example in my answer.
Your answer
Follow this Question
Related Questions
calculating looking angle between 2 transforms 0 Answers
Slerp look at direction not working... 3 Answers
Rotate player (rigidbody) towards his movement 2 Answers
Pose.ctor - create pose from vector3 and quaternion 1 Answer
How to add 2 Quaternions. 2 Answers