C# & Unity : Pass reference by value?

2019-09-18 02:06发布

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.

3条回答
可以哭但决不认输i
2楼-- · 2019-09-18 02:42

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.

查看更多
老娘就宠你
3楼-- · 2019-09-18 03:03

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.

查看更多
祖国的老花朵
4楼-- · 2019-09-18 03:04

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).

查看更多
登录 后发表回答