As it is, your code gives your platform a movement distance of 2 units; 1 unit in either direction of its starting position. To allow further movement, all you need to do is effectively multiply the current movement value.
/// <summary>The objects initial position.</summary>
private Vector2 startPosition;
/// <summary>The objects updated position for the next frame.</summary>
private Vector2 newPosition;
/// <summary>The speed at which the object moves.</summary>
[SerializeField] private int speed = 3;
/// <summary>The maximum distance the object may move in either y direction.</summary>
[SerializeField] private int maxDistance = 1;
void Start()
{
startPosition = transform.position;
newPosition = transform.position;
}
void Update()
{
newPosition.x = startPosition.x + (maxDistance * Mathf.Sin(Time.time * speed));
transform.position = newPosition;
}
By multiplying your movement algorithm of Mathf.Sin(Time.time * speed)
by a distance value of maxDistance
, you effectivley tell your platform to allow movement of maxDistance
units in either direction. The above example gives behavior identical to your current movement; 1 unit of distance in either direction, reversing its direction at -1
and 1
. With maxDistance = 50
, for example, the platform will move between -50
and 50
.
Be aware that as maxDistance
increases, you will likely want a lower speed
. speed
effectively controls how much time it takes to complete an entire movement arc, in this context, not the rate in which it moves in that arc. With maxDistance = 1
and speed = 3
, the platform moves between -1
and 1
over 3 seconds. With maxDistance = 10
and speed = 3
, the platform moves between -10
and 10
over 3 seconds. Due to the much greater distance, the platform will move a lot faster to cover the ground in the same amount of time. To give the same general speed, you would want something more like maxDistance = 10
and speed = 30
. I would personally rename speed
to maxTime
, though I have not done so in the above example.
I will address the semantic alterations I have made, to avoid confusion:
- The addition of
newPosition
gives you a local Vector2 to hold your derived "next position" co-ordinate. We can then work out the updated newPosition.y
value on the fly, and do not have to worry about newPosition.x
before passing it into transform.position
, as this value should not change in the current context.
- Serializing
speed
and maxDistance
with [SerializeField]
serialises these values for the Unity Inspector. As a result, they have retained their private
protection, but you can still change them on the fly from the Inspector.
- Initialising
speed
and maxDistance
inline with the variable declaration simply prevents any Inspector-altered value from resetting when you hit play, and call Start()
. You may wish to have these in Start()
, just remember that these values will then override any values you have provided through the Inspector. For testing purposes, you can still change the values in the Inspector during a play-test to see the effects in-game.
As it stands, you also want to remember that this deliberately constrains movement to a specific value in either direction. That means that this would not work accurately if you wanted less symmetrical movement; for example, it would not work accurately if you wanted your platform to move 20
units to the left, but only allow 10
units of movement in the opposite direction. It could only be constrained to +-10
or +-20
. There are more advanced implementations you could look at to reach this sort of functionality, if needed, though they appear out of scope for the context of this question.