Stone not spawning at correct place after player respawns - c#

When the player reSpawns I want the stones(which can be moved by the player), to go to their original spot. This is not working for me. Instead, the stone spawn on other nearby locations and sometimes off the map. All stones are tagged stone.
I have tried reversing the Vectors and reversing the signs on the subtraction and such.
This is the player script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerControll : MonoBehaviour
{
public bool isTouchingGround = false;
public GameObject locater1;
public GameObject locater2;
public GameObject currentCheckPoint;
public GameObject playerPrefab;
public Rigidbody2D myRigidBody;
public GameObject GameMaster;
// Start is called before the first frame update
void Start()
{
isTouchingGround = false;
GameObject MyGameMaster= Instantiate(GameMaster, new Vector3(0, 0, 0), Quaternion.identity);
GameMaster = MyGameMaster;
}
// Update is called once per frame
void Update()
{
if (Input.GetKey("a"))
{
transform.Translate(-0.1f, 0, 0);
}
if (Input.GetKey("d"))
{
transform.Translate(0.1f, 0, 0);
}
if ((Input.GetKey("w") || Input.GetKey("space")) && isTouchingGround == true)
{
myRigidBody.AddForce(new Vector2(0f, 130f));
}
if (locater1.transform.position.y <= locater2.transform.position.y)
{
ReSpawn();
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Platform" || collision.gameObject.tag == "Stone")
{
isTouchingGround = true;
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if ((collision.gameObject.tag == "Platform" || collision.gameObject.tag == "Stone") && locater2.transform.position.y > collision.transform.position.y)
{
isTouchingGround = false;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.tag == "CheckPoint")
{
currentCheckPoint = collision.gameObject;
}
if (collision.gameObject.tag == "Radiation")
{
ReSpawn();
}
}
public void ReSpawn()
{
GameMaster.gameObject.GetComponent<ReverToOriginalPositions>().RevertToOrignalPosition();
GameObject currentPlayer=Instantiate(playerPrefab, currentCheckPoint.transform.position, currentCheckPoint.transform.rotation);
currentPlayer.GetComponent<PlayerControll>().isTouchingGround = false;
Destroy(this.gameObject);
}
}
This is the RememberPositions script. This belongs to every stone to remember the position is has during the start.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RememberPositions : MonoBehaviour
{
public float StartXPosition;
public float StartYPosition;
float StartRotation;
// Start is called before the first frame update
void Start()
{
StartXPosition = transform.position.x;
StartYPosition = transform.position.y;
StartRotation = transform.rotation.z;
}
// Update is called once per frame
void Update()
{
}
}
this is the RevertToOriginalPosition Script. This reverts the stones to their original positions. This is in the GameMaster/MasterControll.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ReverToOriginalPositions : MonoBehaviour
{
public GameObject[] allStones;
// Start is called before the first frame update
void Start()
{
allStones = GameObject.FindGameObjectsWithTag("Stone");
}
// Update is called once per frame
void Update()
{
}
public void RevertToOrignalPosition()
{
for (int i = 0; i < allStones.Length; i++)
{
allStones[i].gameObject.transform.Translate((new Vector3((allStones[i].gameObject.GetComponent<Transform>().position.x- allStones[i].gameObject.GetComponent<RememberPositions>().StartXPosition) , (allStones[i].gameObject.GetComponent<Transform>().position.y- allStones[i].gameObject.GetComponent<RememberPositions>().StartYPosition), 0)));
allStones[i].gameObject.transform.Rotate(0, 0, -allStones[i].gameObject.transform.rotation.z);
}
}
}
This is the Store reciever Script. This is for another game mechanic called an Activator. This is not that important but I am including it anyway.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class StoreReciever : MonoBehaviour
{
public GameObject reciever;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter2D(Collider2D collision)
{
reciever.gameObject.GetComponent<PolygonCollider2D>().enabled = true;
}
void OnTriggerExit2D(Collider2D collision)
{
reciever.gameObject.GetComponent<PolygonCollider2D>().enabled = false;
}
}
No error messages at all. Just Stones reSpawning in locations they are not supposed to. Thank You for helping.

Just make some fields/properties they dont even have to be private static readonly
public static readonly Vector3 StartPos = new Vector3(1.0f, 2.0f, 3.0f);
public static readonly Vector3 StartRot_In_EulerAngles = new Vector3(1.0f, 2.0f, 3.0f);
Then you can do something like this in a method:
public static void ResetMyStones()
{
var allStones = GameObject.FindGameObjectsWithTag("Stone");
foreach(var stone in allStones)
{
stone.transform.position = StartPos;
stone.transform.eulerAngles = StartRot_In_EulerAngles;
}
}
About Euler Angle:
Why Euler Angle? - because for rotations Unity uses so called Quaternions, so Gimbal lock will not happen, but the bad thing about this is that you cannot really set x y z component individually without deep understanding of Quaternions, however if you just wanna set and get a current rotation Euler Angle is perfect, because you can use the traditional x,y,z components for setting the value.
Additional Notes:
Your code is kinda long and not well structured, like ReverToOriginalPositions should be a method and not a component, also not evrything has to be a derived from monobehaviour.
Also remove the unused Update methods, they have a small overhead if its in a script but not used(Usually its immeasurable but in bigger project it can effect performance :)), and maybe if your game is structured that way you could store all your current stones in a GameManager class list so you dont need to call GameObject.FindGameObjectsWithTag("Stone");

Related

Is there a way to have Delay timer or cutscene? Unity March 28/21 update

What I'm trying to do is have my player stop moving so I can play animation through a trigger-event or just a custscene.
What I expect was for one of them to trigger the timer then play animation>player move.. like a cut-scene
Also there are no errors In any of them They just didn't stop player from moving or just stop the player when starting the game(or when I press play it just set forwardMovement to 0)
Here's the code I use:
public class Player_controls : MonoBehaviour
{
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
public int forwardMovement = 1000;
public void Update()
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
}
Things that I tried:
public void ForwardMovement()
{
forwardMovement = 0;
Invoke("Action", 2f);
}
public void Action ()
{
forwardMovement = 1000 ;
}
Which only works for ForwardMovement(); method nothing else
I tried these two things also:
Public static class MonoExtensions
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public float Delayer = 10f;
public static class MonoExtensions
{
public static void Timed_delay(this MonoBehaviour mono,Action function, float Delayer)
{
mono.StartCoroutine(Timed_delayRoutine(function,Delayer));
}
static IEnumerator Timed_delayRoutine(Action function, float Delayer)
{
yield return new WaitForSeconds(Delayer);
function();
}
public class `Player_Controls`: MonoBehaviour
{
public void PM ()
{
forwardMovement = 0;
}
void OnTriggerEnter(Collider other)
{
if (CompareTag("Power_up"))
{
this.Timed_delay(PM, Delayer);
}
}
}
Which just stop the player from moving an nothing else.
What I also tried was:
public class Player_Controls : MonoBehaviour
{
void Start()
{
StartCoroutine(ForwardMovement());
}
IEnumerator ForwardMovement()
{
forwardMovement = 0;
yield return new waitforseconds(Delayer);
forwardMovement = 1050;
}
void OnTriggerEnter(collider other)
{
if (CompareTag("Power_up"))
{
ForwardMovement();
}
}
}
Which did not work as in(it works but the timer part does nothing, so the player can't move when started the game )
Different way I tried
public class Player_Controls : MonoBehaviour
{
OnTriggerEnter(collider other)
{
Startcroutine(ForwardMovement ));
}
}
it didn't work but no Errors.
I tried this one by jazzhar:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
// Drag the player in the inspector here;
public Rigidbody rb;
// Youre speed variable for movement.
public float Speed = 5;
// Youre speed variable for movement.
public int forwardMovement = 1000;
// Set this "stopmoving" bool to true to prevent movement.
public bool stopMoving = false;
// Create and select the right layer in the inspector.
public LayerMask WichObjectStopsMovement;
public void Update()
{
// if stopMoving = true than Dont Add force.
if (stopMoving == false)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
// if you're player touches a object and that object's layer
// is the same as "WichObjectStopsMovement" than disable Movement.
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = false;
}
}
}
It sorta works in a way if you set if
if (stopMoving == true)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
and
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = true;
}
then the player would be able to move but it will not trigger if hit the cube
it didn't work either but no Errors.
And some other timers I did but forgotten....
_________________________________________________________________March/6/21
public float Delayer = 10.0f;
I think found solution by doing this
private void OnTriggerEnter(Collider other)
{
if (CompareTag("Power_up"))
{
Delayer -= Time.deltaTime; <- this part giving me the error
if (Delayer => 0)
{
forwardMovement = 0;
}
}
}
but their one problem it giving me the this error Cannot convert lambda expression to type 'bool' because it is not a delegate type [Assembly-CSharp]csharp(CS1660) I don't know much about this even searching about doesn't help either
__________________________________________________________________March 28/21
this script is under player controls
this one works I made sure by doing Debug.Log("test");
void OnTriggerExit(Collider collision)
{
if (collision.gameObject.CompareTag("Power_up"))
{
forwardMovement = 0;
}
if (forwardMovement <= 0)
{
Debug.Log("test");
}
This might be a solution to you're problem, Fire-Source!:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
public class Player_controls : MonoBehaviour
{
// Drag the player in the inspector here;
public Rigidbody rb;
// Youre speed variable for movement.
public float Speed = 5;
// Youre speed variable for movement.
public int forwardMovement = 1000;
// Set this "stopmoving" bool to true to prevent movement.
public bool stopMoving = false;
// Create and select the right layer in the inspector.
public LayerMask WichObjectStopsMovement;
public void Update()
{
// if stopMoving = true than Dont Add force.
if (stopMoving == false)
{
rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime);
}
}
private void OnCollisionEnter(Collision collision)
{
// if youre player touches a object and that object's layer
// is the same as "WichObjectStopsMovement" than disable Movement.
if (collision.collider.gameObject.layer == WichObjectStopsMovement)
{
stopMoving = false;
}
}
}
This code uses a LayerMask, to create 1 click on any object and in the inspector go:
Click on Layer:
Add Layer:
Write in User Layer 6, StopMovement (or anything else).
Than in the object that should stop player movement:
Click on layer:
Than select the Layer that says StopMovement.
And in you're player's script drag the object into the rb variable.
and in "WichObjectStopsMovement" assign the StopMovement layer.
This should take care of everything is that ok?

I'm trying to make as so, on trigger, the player stops moving

I'm developing a TopDown 2D game in Unity.
The idea is, when the player steps on a certain tile, a UI with text pops up (already working) and the player stops moving until the player clicks a button (already programmed and working) and the UI disappears.
I was advised to turn the RigidBody2D to kinematic however it doesn't work and it just does what it used to do.
Am I doing something wrong?
Here is the code for the trigger script on the tiles:
public class TriggerScript : MonoBehaviour
{
public string popUp;
public void Start()
{
}
private void OnTriggerEnter2D(Collider2D collision)
{
Rigidbody2D Player = GameObject.Find("Player").GetComponent<Rigidbody2D>();
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
if (collision.gameObject.tag == "Player")
{
pop.PopUp(popUp);
Player.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Kinematic;
}
}
private void OnTriggerExit2D(Collider2D collision)
{
Rigidbody2D Player = GameObject.Find("Player").GetComponent<Rigidbody2D>();
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
pop.closeBox();
Player.GetComponent<Rigidbody2D>().bodyType = RigidbodyType2D.Dynamic;
}
}
PopUpSystem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
public class PopUpSystem : MonoBehaviour
{
public GameObject popUpBox;
public Animator popupanimation;
public TMP_Text popUpText;
public PLayerController mb;
public void PopUp(string text)
{
popUpBox.SetActive(true);
popUpText.text = text;
popupanimation.SetTrigger("pop");
}
public void closeBox()
{
popupanimation.SetTrigger("close");
mb.camMove = true;
}
}
PLayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PLayerController : MonoBehaviour
{
private Rigidbody2D MyRB;
private Animator myAnim;
[SerializeField]
private float speed;
public bool camMove = true;
// Start is called before the first frame update
void Start()
{
MyRB = GetComponent<Rigidbody2D>();
myAnim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (camMove)
{
MyRB.velocity = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed * Time.deltaTime;
myAnim.SetFloat("moveX", MyRB.velocity.x);
myAnim.SetFloat("moveY", MyRB.velocity.y);
if ((Input.GetAxisRaw("Horizontal") == 1) || (Input.GetAxisRaw("Horizontal") == -1) || (Input.GetAxisRaw("Vertical") == 1) || (Input.GetAxisRaw("Vertical") == -1))
{
myAnim.SetFloat("LastMoveX", Input.GetAxisRaw("Horizontal"));
myAnim.SetFloat("LastMoveY", Input.GetAxisRaw("Vertical"));
}
}
if (!camMove)
{
MyRB.velocity = new Vector2(0, 0);
}
}
}
TriggerScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerScript : MonoBehaviour
{
public string popUp;
Animator popAnim;
public PLayerController mb;
private void Start()
{
popAnim = GameObject.FindGameObjectWithTag("PopUpBox").GetComponent<Animator>();
}
private void OnTriggerEnter2D(Collider2D collision)
{
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
var myp = GameObject.FindGameObjectWithTag("Player").GetComponent<PLayerController>();
if (collision.gameObject.tag == "Player")
{
pop.PopUp(popUp);
mb.camMove = false;
}
if (popAnim.GetCurrentAnimatorStateInfo(1).IsName("close"))
{
mb.camMove = true;
Debug.Log("close");
}
}
private void OnTriggerExit2D(Collider2D collision)
{
PopUpSystem pop = GameObject.FindGameObjectWithTag("GameManager").GetComponent<PopUpSystem>();
pop.closeBox();
}
}
Things to keep in mind:
1- Make a new tag and call it PopUpBox. then assign this tag to the Trigger GameObject.
2- To the button of the PopUpBox GameObject (the one which is disabled) assign GameManager GameObject and in its function select PopUpSystem.closeBox
3- In both Trigger GameObject and GameManager assign Player in Mb field.
Hope this help you. You can play with that more to get better results.

Why doesn't "OnTriggerEnter2D()" work when two specific objects collide?

I am creating this flappy bird style game in unity with C#.
I have a scored function in the Game Controller script. Here it is...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class GameController : MonoBehaviour
{
private int score = 0;
public float starScrollSpeed;
public float groundScrollSpeed;
public float skyScrollSpeed;
public GameObject gameOverText;
public GameObject playAgain;
public bool gameOver = false;
public static GameController instance;
public Text scoreText;
// Start is called before the first frame update
void Awake()
{
if(instance == null)
{
instance = this;
}
else if(instance != this)
{
Destroy(gameObject);
}
}
// Update is called once per frame
void Start()
{
}
void Update()
{
}
public void BirdScored()
{
if (gameOver)
{
return;
}
score++;
scoreText.text = "SCORE " + score.ToString();
}
public void PlaneDestroyed()
{
gameOverText.SetActive(true);
playAgain.SetActive(true);
gameOver = true;
}
}
Actually Bird and Plane is the same thing.
What I want to do is to make the bird score/run the BirdScored() function when the Plane overlaps with a star. The Plane has a Rigidbody2D and a collider and stars have a Rigidbody2D but no collider because In the bird script if the plane collide, it destroys.
Here is the Bird Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bird : MonoBehaviour
{
private bool isDead = false;
private Rigidbody2D rb2d;
public float upforce = 200f;
private Animator anim;
// Start is called before the first frame update
void Start()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (isDead == false)
{
if (Input.GetMouseButtonDown(0))
{
rb2d.velocity = Vector2.zero;
rb2d.AddForce(new Vector2(0, upforce));
}
}
anim.SetTrigger("Flap");
}
void OnCollisionEnter2D()
{
isDead = true;
anim.SetTrigger("Die");
GameController.instance.PlaneDestroyed();
}
}
And here is the star script...
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Stars : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.name == "Plane")
{
GameController.instance.BirdScored();
}
}
}
What is wrong and what should I do?
Put a Colider2D on the star, and check the Is Trigger option in the inspector.
The Is Trigger is disable the collision with any other collider2d so your plane wont be destroyed by the OnCollisionEnter2D, but the OnTriggerEnter2D will trigger properly.
I can see in your screenshot that the collider isn't set to "is trigger", which makes it unable to register trigger collisions.

Assets/sucriptusu/movement/onflor.cs(23,13): error CS0120: An object reference is required for the non-static field, method, or property 'zoom.upZoom'

so I'm trying to get this code to run, but its asking something about static which I don't really get. any help would make me happy :).
basically I wanted to make it so every time you jump your jump height would be lower.
and that error at the top came out which I honestly (even after searching a bit) have no idea what it means.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class zoom : MonoBehaviour
{
// Start is called before the first frame update
public float zoomSpeed = 5f;
public float upZoom = 20f;
public bool flor = false;
public float jumpamount = 5f;
void Start()
{
}
// Update is called once per frame
void Update()
{
Jump();
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0f, 0f);
transform.position += movement * Time.deltaTime * zoomSpeed;
}
void Jump()
{
if (Input.GetButtonDown("Jump") && flor == true);
{
upZoom = (upZoom - jumpamount);
gameObject.GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, upZoom), ForceMode2D.Impulse);
}
}
}
other one
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class onflor : MonoBehaviour
{
GameObject mouseplayerreal;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
mouseplayerreal = gameObject.transform.gameObject;
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Guroundo")
{
zoom.upZoom = 20f;
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.tag == "Guroundo")
{
}
}
}

unity5 enemyDamage prob

im having a problem from my enemyDamage script in unity5 when i play it and stick to the enemy i died instantly even the enemy damage is 10 and my health was 100
well this is my first time to make this things on unity hope you helps me :(
heres my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class enemydmg : MonoBehaviour {
public float damage;
public float damagerate;
public float pushbackforce;
float nextdamage;
bool playerInRange = false;
GameObject theplayer;
playerHealth theplayerhealth;
// Use this for initialization
void Start () {
nextdamage = Time.time;
theplayer = GameObject.FindGameObjectWithTag ("Player");
theplayerhealth = theplayer.GetComponent<playerHealth> ();
}
// Update is called once per frame
void Update () {
if (playerInRange)
Attack ();
}
void OnTriggerEnter (Collider other)
{
if (other.tag == "Player")
{
playerInRange = true;
}
}
void OnTriggerExit (Collider other)
{
if (other.tag == "Player")
{
playerInRange = false;
}
}
void Attack()
{
if (nextdamage <= Time.time)
{
theplayerhealth.addDamage(damage);
nextdamage = Time.time + damagerate;
pushback (theplayer.transform);
}
}
void pushback(Transform pushObject)
{
Vector3 pushDirection = new Vector3 (0, (pushObject.position.y - transform.position.y), 0).normalized;
pushDirection *= pushbackforce;
Rigidbody pushedRB = pushObject.GetComponent<Rigidbody> ();
pushedRB.velocity = Vector3.zero;
pushedRB.AddForce (pushDirection, ForceMode.Impulse);
}
}
and this was my playerhealth
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerHealth : MonoBehaviour {
public float fullhealth;
float currentHealth;
// Use this for initialization
void Start () {
currentHealth = fullhealth;
}
// Update is called once per frame
void Update () {
}
public void addDamage(float damage)
{
currentHealth -= damage;
if (currentHealth <= 0) {
makeDead ();
}
}
public void makeDead()
{
Destroy (gameObject);
}
}
theplayerhealth = theplayer.GetComponent<playerHealth> ();
I think this line of code fails you because the player is a GameObject. theplayerhealth is or should already be initialized in your other script. I think you could approach polymorphism in a better way.
public class enemydmg : playerHealth{
}
This will allow you to directly inherit everything you need from the playerHealth script without having to grab extra components. You can also use this technique for may other scripts in the future.
Another approach that you could use is calling your class directly:
playerHealth.addDamage(damage);
From now on when you name your scripts use capitalization. PlayerHealth, EnemyDamage, etc... That's just a pro-tip to make your code look a bit cleaner when you're doing things like this. (Optional)

Categories

Resources