why when i try having my player teleport to the object it says this? - c#

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.

Related

Set z transform position of an instantiated GameObject sprite in unity

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.

How to move gameObject to a random object with specific tag

I am trying to figure out how to make an object move to the position of another object that has a specific tag. I currently have an object array that contains all of the "choices" the object has. Then I get a random number from 0 to the number of objects found. I tested this part and it seems to work well.
What I am stuck on is moving the object the script is on to the position of the object the script finds. What I think I need to do is to get the object associated with the index number and its position, but that isn't working. Thanks in advance! Sorry if this question isn't structured correctly, this is my first post!
public class objective : MonoBehaviour
{
GameObject moveTo;
public GameObject[] gameObjectChoices;
public float choiceNumber;
void Start()
{
//get objects with tag and apply it to object array
gameObjectChoices = GameObject.FindGameObjectsWithTag("RandomCheesePoint");
//choose one of the gameObjects in array
choiceNumber = Random.Range(0, gameObjectChoices.Length);
Debug.Log(choiceNumber);
//move object to random object found
transform.position = gameObjectChoices[choiceNumber].gameObject.transform.position;
//problem occurs at gameObjectChoices[choiceNumber]
//error message says "Cannot implicitly convert type 'float' to 'int' An explicit conversion exists (are you missing a cast?)"
}
}
Your problem is you are attempting to index an array using a float value instead of an int.
Random.Range() will return an the same type as it's input parameters (in your case int) but this value is getting implicitly cast to a float because you declared your variable as:
public float choiceNumber;
If you change this to:
public int choiceNumber;
Then your code should work perfectly.

Why I can not refer an object in Unity?

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.

C# & Unity : Pass reference by value?

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.

Assigning and method call order

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.

Categories