Confused on Transform and Vector3

In my game I am trying to make a trophy appear in front of the player.  Below is how I attempted to do that.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


public class Intro : MonoBehaviour {


    int x = 1;
    public GameObject trophy, trophyCopy, player;
    Transform playerTrans;


    public void Update()
    {
        x++;


        if (x == 6200)
        {
            playerTrans = player.GetComponent<Transform>();
            playerTrans.x += 5;
            trophyCopy = Instantiate(trophy, playerTrans.position, playerTrans.rotation);
        }
    }
}



I drag the player into the player variable slot in the inspector. The issue I am having is that I get the following error. 

Severity    Code    Description    Project    File    Line    Suppression State

Error    CS1061    'Transform' does not contain a definition for 'x' and no extension method 'x' accepting a first argument of type 'Transform' could be found (are you missing a using directive or an assembly reference?)    Kids Math Game    C:\Users\Hunter\Documents\Kids Math Game\Assets\Scripts\Intro.cs    70    Active


I suspect that I should be using a Vector 3 somewhere in here but I am not sure where or why Transform doesn't have a definition for x. Any idea what I am doing wrong?

  • Jonathan Gonzalez(jgonzalez) replied

    You can't modify just one axis at a time like that. You'd need to reference an entire Vector3. I haven't test this code out but it should be something like this:


    playerTrans.position = new Vector3 (transform.position.x +5, transform.position.y, transform.position.z);
    
    
    

    I'd also recommend the following changes to your script. Since you already have a player variable for the GameObject you can use that same one for the transform. You'd reference it like this:


    player.transform.position
    


    That's useful if you want to reference both the game object of the player but also access the transform. Along with that, I don't recommend using GetComponent in the Update method. You only need to get that component once, so use it in the Start or Awake method instead. Otherwise you're telling it to get the transform component many times per second.



  • Ken Claassen(cptken) replied

    A transform relates to more than just a position. It defines position, rotation and scale all of which have their own x, y, z. (Well actually behind the scenes its a 4x4 matrix but that's not something you need to worry about).

    Hence to access these orientation aspects you need to use transform.position, transform.rotation and transform.scale then you could add the .x, .y, .z, w etc. However, I wouldn't recommend doing that exactly for performance reasons. Where you can you should use transform.localPosition, transform.localRotation and transform.localScale so long as you know the object is not parented to another object. The reason being is that the former method actually calls a function to calculate the global position while the latter just spits out the localPosition as is. Thing is,  if your object is not parented, it's local position ==  global position so the result will be the same either way. It's just a good habit to get into. This may seem like nothing and in this particular script you won't notice a difference but once games get big and complex these things start to matter so just a tip.

    A few other things:

    1. Don't ever instantiate an object in the Update function if you can help it. I'd recommend instantiating it in the Start() function and then using GameObject.SetActive(false) to hide it immediately after. When you want to show it in the update function use GameObject.SetActive(true).

    2. Don't use GetComponent() in an update function, use it in start and save the result for use later. In the case of a transform, the GetComponent() function is not necessary because you can simply use object.transform.

    3.  If you want to move an object like you are doing it may be better to use transform.Translate function instead.

    4.  I'm not sure exactly what the intent of your code is but it seems like you're incrementing the x integer as a kind of timer. Problem with this is that if you are running at different FPS, the timer will be different every time. Instead in the start function save a float with the current time using Time.time. Then say if you want it to only happen after ten seconds you would go if(Time.time > savedTime + 10) { }


    That's a lot of information so don't worry if it doesn't all make sense straight away. Takes a long time to get used to this stuff.