I don't know how can I do it. You lose a game, if gameobject falls down and collides with the collider. I want to add a function that asks to the player if he wants another try, if yes it will reverse some time so the gameobject that fall down will be back on the screen and the user is allowed to play once again. Is there some sort of time function/method to do this?
Hope you understand.
void OnCollisionEnter2D(Collision2D col) {
if(col.gameObject.tag=="Collider") {
Vector2 checkpoint = new Vector2(transform.position.x, transform.position.y +5)
}
}
void Reset(){
this.transform.position = checkpoint;
}
I created a child object for that collider. And I moved the child to where I wanted the player to live when I collided with the collider.
Void OnCollisionEnter2D(Collision2D col)
{
if(col.gameobject.tag=="die")
{
checkpoint = col.transform.GetChil(0).position;
}
}
void Reset(){
Player.transform.position = checkpoint;
}
Your error is because you are missing the new keyword before Vector2
When using C# you need to use the new keyword in front of all
constructors. Constructors are like functions that are used to create
new objects (or scructs). They always have the same name as the type
of object you are creating.
So you should write
Vector2 checkpoint = new Vector2(transform.position.x, transform.position.y +5)
instead of:
Vector2 checkpoint = Vector2(transform.position.x, transform.position.y +5)
Edit: Now you edited your question without the error, and since you are still trying to find a method that moves back in time what happened in Unity, I can tell you that that thing doesn't exist. However you can implement it yourself. I would recommend you something like this:
If it is a platform 2D game, like Mario Bros style, you can place in
your scene a sequence of trigger that are activated when the player
go through them.
Then you can have a boolean array with a length n equal to the
number of triggers, and then a matrix nx2 ( number of triggers x
coordinates of each trigger [x,y] ).
Initially all the elements in the array has a false value, and
every time a trigger is activated the correcponding element in the
array changes to true.
When the player dies, it checks all elements in the array, until it
reaches the last true element (this would be the last triggered
activated).
With the index form the previous step you access the matrix of
triggers and you extract both elements (x and y coordinate). Then you
use that value in:
Using your script:
Vector2 checkpoint = new Vector2(xCoordinate, yCoordinate);
There is no in built function to reverse time in unity, this would require unity to record all events up until that point.
But given your example, what you could do is create a 'checkpoint' where the scene is set up in a certain way and objects are in specific positions. Like in Mario where you fall down, it plays some music to show you failed then it puts Mario back in a certain position. Just have a function that changes the player position to the checkpoint position. The same applies to any other gameobject you need to reset.
public void Reset()
{
player.position = checkpoint.position;
}
Related
I am making a game and am fairy new to this language and I need to detect if a sprite has reached a certain location for the game to have some sort of response.
something like;
if ( /* position of sprite1 == (100,400) */ )
{
// Do stuff;
}
First, you need to have an Vector2 variable that keeps their position stored.
Then, you can use that Vector2 to compare one position with another.
A possible idea is to use it like this:
Vector2 position = new Vector2(0,0);
if (position == new Vector2(100, 400))
{
//Do stuff
}
and then in the place where you draw your sprite, you replace the sprite's location with the position variable.
Keep in mind though, position checking is very precise, if you miss on one pixel, you won't be triggering the if-statement.
Often, you rather want to do collision checking using Rectangle, so you have a whole 'hitbox' to check positions with. Though that depends on the context of your game.
I am making this 2D platform game for a freelance, and I have to do a sonic mechanic, I have to make the character run through a full loop without falling down, I realised that to do this first I would have to rotate the character conform he runs through the loop, but the second part is where I am stuck.
So, basically, how can I make the character run the loop without falling down.
private void OnCollisionEnter2D(Collision2D coll)
{
Vector3 collRotation = coll.transform.rotation.eulerAngles;
if (coll.gameObject.tag == "Ground")
{
//in this part i rotate the player as he runs through the loop
transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, collRotation.z);
//this is the part that i am stuck, trying to figure out how to make the character stay in the loop without falling, i tried collision detection,
//i tried raycasting but nothing seems to work
if (IsGrounded)
{
GetComponent<Rigidbody2D>().AddForce(Vector2.down, ForceMode2D.Impulse);
}
}
}
The trick that is most commonly used for remakes and similar is getting the speed of the player character on entry.
// Feel free to adjust this to whatever works for your project.
const float minimumAttachSpeed = 2f;
// This should be your characters current movement speed
float currentSpeed;
// You need a Rigidbody in this example, or you can just disable
// any custom gravity solution you may have created
Rigidbody2D rb;
If the speed of the character is excelling the minimum attachment speed, you can then allow them to follow a predefined path at that speed.
bool LoopAttachmentCheck()
{
return minimumAttachSpeed <= currentSpeed;
}
And now you can check to see if you're moving fast enough! I assume for this example you are using a Rigidbody2D...
(this check should only be run when you're either entering or currently on the loop)
void Update()
{
if( LoopAttachmentCheck() )
{
// We enable this to prevent the character from falling
rb.isKinematic = true;
// Here you write the code that allows the character to move
// in a circle, e.g. via a bezier curve, at the currentSpeed.
}
else
{
rb.isKinematic = false;
}
}
It's up to you to implement the actual rotational behaviour. If I were you, a good way to do this would (assuming it is a perfect circle) use RotateAround from the center of the circle.
If you have more complex shapes, you can use waypoints for movement, and just iterate through them at your speed.
The moment you fail to keep up speed, your character will fall off (so if a player decided to stop running for example) and the Rigibody2D will become kinematic.
Hope this helps!
In my 2D side-scrolling game I move my character using the built-in physics engine by manipulating the rigidbody.velocity.
I would like to add some sort of dodge (roll) ability, where the character moves 3 units in its direction.
Here is the code I used:
void FixedUpdate() {
if (Input.GetKeyDown(KeyCode.A) ) {
Vector2 pos = rb.position;
pos.x -= 5;
rb.MovePosition (pos);
}
}
This method works but the character kind of jumps to the position rather than moving to it (Lerping?) and also doesn't detect collisions despite the body type being dynamic.
Then I tried this:
if (Input.GetKeyDown(KeyCode.A)) {
rb.AddForce(new Vector2(-50, 0));
}
I found the AddForce way isn't accurate at all.
Is there a proper way of doing this?
Maybe you could change the Transform.pos inside Vector2.Lerp to make it look smooth? (Sorry, not enough experience with 2D in unity.)
Just increase rigibody.velocity for a set time. Your chararter object could then play a fitting aniamtion. If The player should not be able to cancle midrole jsut block the controls for that time.
I am trying to spawn 2 Players (host and client) at 2 different locations.
I have no idea how to do this because the player are automatically spawned by the network manager.
I have tried the following but failed horribly :(.
[Command]
void CmdSpawn()
{
var go = (GameObject)Instantiate(
gameObject,
transform.position + new Vector3(0,1,0),
Quaternion.identity);
NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
}
How Can I Spawn Player object at a specific location?
NetworkManager already supports spawn positions.
Just add GameObjects where you want players to spawn and give them the NetworkStartPosition component. NetworkManager will automatically detect the start positions and automatically use them according to your setting of "Player Spawn Method" either "Random" (one spawn position is randomly chosen for every player) or "Round Robin" (player #0 spawns at first position, player #1 at second and so forth).
Is there any problems with changing position in a script for player object? For example you could try adding following script on your player object:
void Start () {
if (isServer) // host runs
{
transform.position = new Vector3(0,0,0);
}
else if (isClient) // client runs
{
transform.position = new Vector3(10,0,10);
}
}
i was facing a similar problem, here is the solution in this thread, read til the end.
http://forum.unity3d.com/threads/which-function-to-override.391076/
Make a GameObject and attach a NetworkStartPosition to it. Then, place it somewhere. If you want more than 1 spawn point, you can CTRL+D that object. Then, go to NetworkManager and select Round Robin for spawning first to first, second to second etc. select Random for random spawn points.
Background: I've been doing a lot of studying in xna lately. I've been perfecting my game structure and creating essential classes for an average game, read a couple articles, watched a number of videos, and read bits of a book I have. So, after creating a good game structure I moved on to the actual game, a platformer. I currently have ordinary blocks, and a Player - and the problem is within the player.
Problem/Question: Colliding with blocks is usually fine, but sometimes collisions act strangely. IE: Some how the player is in the block ( normally one pixel in ), and this is a big problem because this could cause the player to be pushed some where across the map.
Player Game Logic: The player's movement is state based. The states are an enumerator of "ground, jump, and fall". Right now, the problem seems to be inside of the falling state. Sometimes the collision works correct, sometimes the player ends up one pixel inside of the block - which means if the player jumps he will be instantly pushed to the first block above the player - no matter how far.
Collision Logic: Inside the fall state the player is pushed towards the floor by gravity. Gravity gets added by the force every frame. Before changing the position, a collision method is called upon checking if there was a collision between any block within it's range of motion. Now, since this is a falling state the player is moving down, so when it collides a while loop pushes the player down by 1pixel every frame until it's meeting the block. And just as a back up, there's a loop that pushes the player out of the block. Then it sets the current state to ground. The jumping state follows the same kind of theory.
Falling State Script: Read above for explanation of this code.
case PlayerState.Fall:
// falling sprite
mySpriteManager.mySpriteCurrent = mySpriteManager.mySpriteIndex["PlayerSprites/player_fall"];
// fall velocity change
myVelocity.Y += myDforce;
if ( Collision( otObjectList.wallIndex, myPosition.X + 1, myPosition.Y, myPosition.X + myWidth - 1, myPosition.Y + myHeight + myVelocity.Y) )
{
while( !Collision( otObjectList.wallIndex, myPosition.X + 1, myPosition.Y, myPosition.X + myWidth - 1, myPosition.Y + myHeight) )
myPosition.Y += 1;
while ( Collision(otObjectList.wallIndex, myPosition.X + 1, myPosition.Y, myPosition.X + myWidth - 1, myPosition.Y + myHeight))
myPosition.Y -= 1;
myVelocity.Y = 0;
myCurrentState = PlayerState.Ground;
}
else
{
myPosition.Y += myVelocity.Y;
}
break;
Collision Script: This runs through all solid objects until there is a collision and returns true if there is.
private bool Collision( List<ObjWall> otWalls, float x1, float y1, float x2, float y2)
{
myBoundingBox.X = (int)Math.Ceiling(x1);
myBoundingBox.Y = (int)Math.Ceiling(y1);
myBoundingBox.Width = (int)Math.Ceiling(Math.Abs( x2 - x1));
myBoundingBox.Height = (int)Math.Ceiling(Math.Abs( y2 - y1));
foreach (ObjWall wall in otWalls)
{
if ( Box.Intersects( wall.Box ) )
{
return true;
}
}
return false;
}
Variable Explanations:
myBoundingBox - every normal object builds off this abstract class. So, every object has a bounding rectangle.
Box - is a trait that comes from the abstract object class, it just returns the bounding rectangle.
myVelocity - is the players velocity, this is a Vector2 because floats provide cleaner looking gravity.
myDforce - is a float that changes the yvelocity in a positive force. I believe I should make it a constant.
ObjectList - this is a class that runs all Normal Object logic and contains a list of all the possible objects that can be in a room.
myPosition - This is another protected variable provided by the abstract class that normal objects are driven from. This is a vector 2, so it works using Floats.
For any more explanation in the code please ask!
In advance, thanks for your time and Help.
Cay.
Your 2nd call to Collision currently only checks the current position and then moves the Player down regardless of whether that action would cause a collision.
I can see you should be dealing with this with your 3rd call to Collision and moving the player back up but to remove some complexity from your code (slightly), you could simply have the 2nd call to collision checking the position + 1 and not moving the player if true.
This removes the need for the 3rd call to Collision, matches the logic you're using for most of the falling with the first call to collision (i.e. moving by gravity but not if the move would collide with a wall) and reduces the places your error can occur.