Who doesn’t need, from time to time, being able to copy a whole object, with all its attributes, into some reserved place for later retrieval? Well, I do.
For transforms, currently I’m using this:
GameObject initialTransformGO = Instantiate(handlingTransform.gameObject) as GameObject;
initialTransformGO.transform.parent = someGameObjectJustToBeSafe;
The problem is when I want to recover what I just copied, later on, I have to do this:
And I’m not even sure this will cover 100% all cases, since it’s only copying the local (unlike the instantiate, which is copying every little property).
Well this certainly doesn't accomplish the first 2 of those goals. And I couldn't really suggest an alternative without knowing exactly what you are trying to do.
Well, you could implement a simple class to save a position / rotation / scale value and add extension methods to the Transform class that saves / loads the state:
// C#
public class StoreTransform
{
public Vector3 position;
public Quaternion rotation;
public Vector3 localScale;
}
public static class TransformSerializationExtension
{
public static StoreTransform SaveLocal(this Transform aTransform)
{
return new StoreTransform()
{
position = aTransform.localPosition;
rotation = aTransform.localRotation;
localScale = aTransform.localScale;
};
}
public static StoreTransform SaveWorld(this Transform aTransform)
{
return new StoreTransform()
{
position = aTransform.position;
rotation = aTransform.rotation;
localScale = aTransform.localScale;
};
}
public static void LoadLocal(this Transform aTransform, StoreTransform aData)
{
aTransform.localPosition = aData.position;
aTransform.localRotation = aData.rotation;
aTransform.localScale = aData.localScale;
}
public static void LoadWorld(this Transform aTransform, StoreTransform aData)
{
aTransform.position = aData.position;
aTransform.rotation = aData.rotation;
aTransform.localScale = aData.localScale;
}
}
This is just an example and probably not the best
This extension can be used like this:
//C#
Transform someTransform;
var save = someTransform.SaveWorld();
// [...]
someTransform.LoadWorld(save);
You could also add the information which space the saved values are in to the StoreTransform class and only provide one load function, but i think it’s more flexible this way.
Additionally, I think Store has to call a method inside StoreTransform class, instead of implementing it inside itself. Or at least I couldn't figure out a way to fix the errors while doing the way it is right now.
Friggin' awesome! You must be having fun doing this, aren't you? It's just so much work... Thanks a bunch! :) As for the first point, that's not exactly what I meant to say. We got the Transform. We could save only the local positions, plus the parent transform or something maybe, and then, if need to load or restore a global position, calculated it as requested.
I don’t believe there is a way to directly copy the entire transform structure, but independently assigning the position, rotation and scale as you are doing should work fine. Depending on the case, it may be better to use world transform values instead of local. If your goal is to have streamlined code, you could write a utility function like:
Yeah, but that's mostly just restating what I said and not really answering the question! :P meanwhile, main problem with using "world transform" is we have no "world scale" property, as far as I know. O_o
There is lossyScale, but as it's name suggest it probably loses precision, so you're better off using local transforms. I don't see why this solution wouldn't work for you. It definitely addresses the issue of code duplication, reducing 3 lines of code to 1. Yes, it is mostly a repeat of what you already are doing, because that's the way to do it.
Because it is precisely what I was doing already... Except I didn't mention I was using it as a method because I didn't think it was relevant. And sorry for such a late reply. :P Also, it doesn't answer the question at all, because that function will not copy the transform by itself. We still need to create a new GameObject to store the data.
It can’t be done the way I wanted. The Transform class needs a GameObject to exist. I think because it’s a component, not sure. Also, as an object, it just can’t be copied, like we would expect a variable can. Then we’d need a deep copy implementation or something on those lines, and that can get really complex.
Ideally we would expand Transform and implement a Copy method, but it is a sealed class. So, the next best we can do is implement our own transform, which uses Transform. Since its intent is to store its whole data, without needing to create a new game object or separate variable for each parameter, I find it appropriate to call it StoreTransform. And add as many parameters from Transform as needed. I hope this already cover them all, tho.
Usage / Example:
StoreTransform storedTransform = new StoreTransform(transform); // already copied
// toy around with transform
transform.localPosition = Vector3.zero;
// recover data
storedTransform.Make(transform);
Code:
///
/// Enable to store a whole transform without the need of a new game object and all handling there.
/// Using the sealed class Transform would just reference instead of copying data.
///
public class StoreTransform {
public Vector3 localPosition;
public Vector3 position;
public Quaternion localRotation;
public Quaternion rotation;
public Vector3 localScale;
public void Set (Transform origin) { set(origin); }
public void set (Transform origin) {
localPosition = origin.localPosition;
position = origin.position;
localRotation = origin.localRotation;
rotation = origin.rotation;
localScale = origin.localScale;
}
public void Make (Transform destination) {
destination.localPosition = localPosition;
destination.position = position;
destination.localRotation = localRotation;
destination.rotation = localRotation;
destination.localScale = localScale;
}
public StoreTransform () {}
public StoreTransform (Transform origin) {
set(origin);
}
}
Bunny83! long time no see I guess. Don't be sorry to say that, thanks for saying it! I never knew world position were calculated from local. How would you implement this?
Maybe copying a transform is a dead-end solution. What are you trying to accomplish with this?
– flaviusxvii@flavius Reducing lines of code, elegance and eventually preventing unexpected results.
– cregoxWell this certainly doesn't accomplish the first 2 of those goals. And I couldn't really suggest an alternative without knowing exactly what you are trying to do.
– mweldon@mweldon your comment led me to re-read my question, realizing it wasn't very clear indeed and then, while reformulating it, and then finding too much info on the topic: http://stackoverflow.com/questions/10079433/in-c-sharp-what-are-our-options-to-clone-an-object-or-copy-its-properties
– cregox