Is there an easy (shorter) way to set the z transform position of an instantiated game object (sprite) in unity? I want to set each instance to 2 for now.
Here's the one line of code I am using, I just wanted to set the z position and it seems cumbersome to do it this way - ignore the first line as I am only including it to demonstrate how the GameObject has been instantiated:
GameObject laser = Instantiate(laserPrefab, transform.position, Quaternion.identity) as GameObject;
laser.transform.position = new Vector3(laser.transform.position.x, laser.transform.position.y, 2);
Thanks in advance!
There is no simpler way of doing this, but you can create method to make your code assigning new position shorter. For example, creating method like this:
Vector3 SetZ(Vector3 vector, float z)
{
vector.z = z;
return vector;
}
Would let you to set new object's position like this
laser.transform.position = SetZ(laser.transform.position, 2);
You have to use method, because trying to do it directly, using property would result in compile time error.
transform.position.z = 2;
Results in error: CS1612: Cannot modify the return value of 'Transform.position' because it is not a variable
There are some extension methods on Vector3 that might make it a bit more easy to read. But I don't think it will get much shorter than what you wrote:
Like Vector3.MoveTowards
https://docs.unity3d.com/ScriptReference/Vector3.MoveTowards.html
But the short answer might be this: No.
A Vector(2/3) is a struct. In this case its made safe for the user by unity and made fully readonly, as you can't really assign values to a struct, because that would result in a new instance of the struct. So you cannot do assignments like laser.transform.position.z = 2. You will always have to create a new Vector.
Related
My error is
CS0029 Cannot implicitly convert type 'UnityEngine.GameObject' to 'UnityEngine.Vector3'
Code:
{
GameObject snowball = GameObject.Find("LaunchSlingshotProjectile").GetComponent<SnowballThrowable>().projectilePrefab;
GorillaLocomotion.Player.Instance.transform.position = snowball;
}
I tried adding it to a variable but it didn't do anything
GameObject snowball = GameObject.Find("LaunchSlingshotProjectile")
Now snowball is a GameObject;
SnowballThrowable sbthrowable = snowball.GetComponent<SnowballThrowable>();
sbthrowable is a Component.
GameObject tile = sbthrowable.projectilePrefab;
tile is a GameObject variable which defined by yourself.
Vector3 pos = tile.transform.position;
The pos variable's type is Vector3, Only variables of the same type can be assigned.
GorillaLocomotion.Player.Instance.transform.position = pos;
Try
GorillaLocomotion.Player.Instance.transform.position = GameObject.Find("LaunchSlingshotProjectile").GetComponent<SnowballThrowable>().projectilePrefab.transform.position;
Your error is that you are trying to set a position
GorillaLocomotion.Player.Instance.transform.position = ...
which is a Vector3, and you are passing a GameObject for it, so the compiler doesn't understand.
A tip would be storing whatever GameObject.Find("LaunchSlingshotProjectile") is in a variable so that you don't perform this operation all the time, since Find is slow.
I want to create a Vector3 type object referring to my player's position so that I can use a shorter name in my script.But I failed to do it. It seems that the new object pointing at other address.
I wrote some code like this:
//PlayerController.cs
vector3 playerPos = transform.position;
Debug.Log(System.Object.ReferenceEquals(playerPos,transform.position));
The output was
false
What caused this and how can I refer to my player's position correctly?
What caused this
Below is a simple explanation.
transform.position is Vector3.
Vector3 is a struct.
Struct is a value type.
It's always good look in the Unity's Documentation to see which type Unity API is. This really matter when working in Unity.
When you do:
vector3 playerPos = transform.position;
New struct is created and values from transform.position; is copied to playerPos variable. Since the variable is value type and copied, performing System.Object.ReferenceEquals on it should return false.
I want to create a vector3-type object referring to my player's
position so that I can use a shorter
In this case, you have to change the Vector3 to Transform.
Transform myPos = null;
void Start()
{
myPos = transform;
}
then you can do:
myPos.position = newPos;
The reason you have to declare the position as Transform instead of Vector3 is because Transform is a class and a class stores the reference of the object.
class is a reference type.
Debug.Log(System.Object.ReferenceEquals(myPos, transform)); should return true because myPos and transform are both classes and the myPos variable is referencing the transform variable.
So, whenever you access your position with myPos.position;, it will give you the newest position of your GameObject which is also (transform.position) since the myPos variable is a class that has a reference of transform which is also a class.
Assuming that myPos is struct or declared as vector3 myPos instead of Transform myPos, then the myPos variable would hold the copy value of transform.position when it was assigned and will never return the latest position of your GameObject since it is a copy.
You can learn more about class vs struct here.
Finally System.Object.ReferenceEquals says "ReferenceEquals" not "ValueEquals" so this is even self-explanatory. You use it on a class/referece types not on structs or value types.
I'm new to C# and Unity, and here I am tweaking and creating my first minigame.
Here is the problem:
I've got a little cube, that moves. I've implemented a method that checks the next position before making a move.
The method receives as parameters the current cube position, and the direction:
public bool okToMove(Transform playerCurrentPosition , int directionIndex)
{
Transform playerNextPosition = playerCurrentPosition;
playerNextPosition.Translate(toDirection(directionIndex));
if (playerNextPosition.position.x > 1 ||
playerNextPosition.position.x < -1 ||
playerNextPosition.position.y > 1 ||
playerNextPosition.position.y < -1)
return false;
else
return true;
}
Then, I call the method
public void movePlayer(int directionIndex)
{
if ( okToMove(gameObject.transform, directionIndex) )
transform.Translate(toDirection(directionIndex));
}
The problem is that the cube makes 2 moves at once. This is because of
transform.Translate(toDirection(directionIndex));
and
playerNextPosition.Translate(toDirection(directionIndex));
that is called from okToMove method. Unity or C# sees playerNextPosition as the real cube, and not somekind of temporary copy that only exists inside the method.
So why is my gameObject.transform being passed as a reference and not by value? How can I make it work?
Thanks in advance and sorry for my noobiness.
You are passing reference to Transform and then moving it with translate in "okToMove", best way is to make a copy of Vector3, just change your "okToMove" like this.
public bool okToMove(Transform playerCurrentPosition , int directionIndex){
Vector3 playerNextPosition = playerCurrentPosition.position;
playerNextPosition += toDirection(directionIndex);
if (playerNextPosition.x > 1 ||
playerNextPosition.x < -1 ||
playerNextPosition..y > 1 ||
playerNextPosition.position.y < -1)
return false;
else
return true;
}
Transform is component attached to each gameObject and it holds values for position, rotation and scale, so your "playerCurrentPosition" is not copy of position but rather reference to Transform (not a copy).
Create a new GameObject that is a copy of yours original, and use its transform to make your calculations. (This answer is originally from the Unity forums). The official documentation tells me you can use Object.Instantiate to create a clone of a GameObject.
In C#, objects have always their reference passed as value, so simply reassign won't do it. See this related question.
Objects in C# are passed by reference. If you want to copy an object, implement the ICloneable interface which has the method Clone(). You will need to copy the object yourself and return it from this method.
Ok,
I have a matrix of enemies Enemy enemyGrid[x, y]
Then, in my code I get an instance of one of the enemies by calling Enemy tmp = enemyGrid[a, b]
But if I change a property in tmp it is not reflected the next time I load the object from the matrix into the the same object tmp.
Each time I am finished with tmp I need to make it = null to have the change reflected into the object in the gird?
Why is that? I thought that tmp would just hold a reference to the object and changes would be made directly in the main object.
Thanks.
CODE UPDATE:
Populating the grid:
Enemy [,] spriteGrid = new Enemy[countCols, countRows];
spriteGrid[x, y] = new Enemy();
Access an object and change properties:
Enemy tmp = spriteGrid[i, j];
tmp.canShoot = true;
tmp.Update(gameTime, game.Window.ClientBounds);
tmp.canShoot = false;
The last line (canShoot = false) does not reflect into the object stored in the grid.
The line
Enemy tmp = enemyGrid[a, b]
does not create a copy of the object in your matrix. It creates an alias to the same object instance. Changes to tmp do affect the instance in the grid that they alias.
Please post a short, complete code snippet that demonstrates the issue you are experiencing.
UPDATE
In your sample, you set
tmp.canShoot = true;
but then
tmpEnemy.canShoot = false;
Two different variables.
Update 2
#Amry's comment is also accurate... if Enemy is a struct instead of a class, you would see this very behavior. That is because struct is a value type, meaning the assignment does create a copy rather than an alias.
Except for very special cases, you should never use a struct that is mutable (that is, a struct whose value can change after it is initially created).
I wrote such a property (representing direction for my XNA game object):
public Vector2 Direction
{
get { return direction; }
protected set
{
(direction = value).Normalize(); // ***
angle = MathHelper.WrapAngle((float)Math.Atan(direction.X / direction.Y));
}
}
set sets two equivalent fields which represent object's orientation in angle and simultaneously in normalized vector.
Starting game failed because line marked by *** failed. It doesn't normalize vector.
I changed this line to:
direction = value;
direction.Normalize();
and it works fine... Why?
I assumed that in line marked by *** first operation is assigning value and then normalising direction. But it's not true.
___ ___ ____
Normalize() is method from Vector2 class.
//
// Summary:
// Turns the current vector into a unit vector. The result is a vector one unit
// in length pointing in the same direction as the original vector.
public void Normalize();
I am assuming Vector2 is a struct, or value type, which means it is passed-by-value and not by reference. When you assign value to direction, you are setting direction to a copy of value. Additionally, the object returned by the expression (direction = value) is a copy, and not the same instance that is in direction. You are calling Normalize on an object that is never stored outside of the setter block.
For this same reason you cannot call methods or set properties on a struct returned from a property getter on a class. For instance, if the property from your example is in a class named Monkey, note:
Monkey m = new Monkey();
m.Direction = new Vector2(...);
m.Direction.X = 2; // This will not compile.
m.Direction.Normalize(); // This will not do what you expect.