Balance and inertia in Unity - c#

I am making a game, where you have to balance an object on the platform.
But as soon as the object drops on the platform and I move the platform to the left or to the right - the object stays in the same place.
So I tried to add this script to the object:
using UnityEngine;
public class ObjectScript : MonoBehaviour
{
public bool inContactWithPlatform = false;
private Transform platform;
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Platform"))
{
inContactWithPlatform = true;
platform = collision.transform;
transform.SetParent(platform);
}
}
private void OnCollisionExit(Collision collision)
{
if (collision.gameObject.CompareTag("Platform"))
{
inContactWithPlatform = false;
transform.SetParent(null);
}
}
}
So when I move the platform, the object moves as well. But it absolutely does not look realistic and I can't shake the object off the platform.
So, basically what I am trying to get is inertia (velocity? force?) to the object on the platform (like, if I move the platform with the object on it quickly to the side - the object will get inertia and will slide off the platform).

Related

How to freeze camera when the game is paused in Unity?

So recently I started coding my first FPS game. I experienced a problem with my pause menu. The problem is when I have my game paused my mouse is still controling the camera and when I want to press some buttons in menu camera keeps following my mouse. I searched for solution to this problem on web, but I haven't found the solution (even my code is similar to some I've found).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class PauseMenu : MonoBehaviour
{
public static bool gameIsPaused;
public GameObject pauseMenuUI;
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
Pause();
}
}
public void Resume()
{
Cursor.lockState = CursorLockMode.Locked;
pauseMenuUI.SetActive(false);
Time.timeScale = 1f;
gameIsPaused = false;
}
void Pause()
{
Cursor.lockState = CursorLockMode.None;
pauseMenuUI.SetActive(true);
gameIsPaused=true;
Time.timeScale = 0f;
}
public void LoadMenu()
{
Time.timeScale = 1f;
SceneManager.LoadScene("Menu");
}
public void QuitGame()
{
Debug.Log("Quitting game...");
Application.Quit();
}
}
What I would do is to update the camera according to the pause conditon. like so:
public class CameraRotation : MonoBehaviour
{
public isGamePaused; // changed from outside when you pause/unpause the game
void Update()
{
if (isGamePaused) {
...
}
}
}
The problem with gameIsPaused (usual code convention naming to state is a bool would be isGamePaused :)) is that until you set it to true in the menu the camera will keep moving, so you may need to set the boolean to true at the time the menu pops up.
Even its not the suited case for static variables, if you want to check the pause state of your game from the camera script, you can do so like this:
public class CameraRotation : MonoBehaviour
{
public isGamePaused; // changed from outside when you pause/unpause the game
void Update()
{
if (PauseMenu.gameIsPaused) {
...
}
}
}
static stands for static in memory, so the variable value can be checked anytime from anywhere with ClassName.staticVariableName. With this I mean that as long as you set the PauseMenu.gameIsPaused variable at the times in the code where you´d like you should be able to make it work, by working I mean freeze/unfreeze the camera at the exact moment you want.
Your static PauseMenu.IsPaused is fine and a good way to do it although I usually put something like that on a GameManager class. You can find a Unity Singleton pattern online so you can start having PauseMenu.Instance.XXX so it's easy to access anything you need. That being said, you need to find the script controlling your camera and check the PauseMenu.IsPaused. Most likely you have a script attached to your camera, and all you generally need to do is find the Update() function and just do: if (PauseMenu.IsPaused) return; to stop it from working.

Game object can't detect others when using collision.gameObject.tag in unity

I have designed a scenario as below:
I created an object spawner to collide with things tagged as "ob", using a boolean to manage the timing to spawn new obstacles. Nonetheless, after some testing, I found that it seemed like nothing had ever collided with one another(Judged by the strings I put in the if condition had never shown in the console.) Can't figure out why! Please HELP!!!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class newObSpawning : MonoBehaviour
{
public GameObject[] oblist;
private bool hasOb=true;
public float adjustSpawnx;
void Update()
{
if (!hasOb)
{
spawnObs();
hasOb = true;
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("ob"))
{
hasOb = true;
Debug.Log("hasOb"); //just for testing
}
}
private void OnTriggerExit2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("ob"))
{
hasOb = false;
Debug.Log("hasOb");
}
}
public void spawnObs()
{
int i = Random.Range(0, oblist.Length);
Debug.Log(i);
float y = 7.87f;
GameObject newob = Instantiate(oblist[i], new Vector3(transform.position.x+ adjustSpawnx,y,0), Quaternion.identity);
}
}
obspawner carry a "follow player" script to move at the same pace as the player,and it went just well
Your player doesn't seem to have a Rigidbody2D component. Add Rigidbody2D to your player. A collider can only emit OnTriggerEnter2D or OnTriggerExit2D events if there is a rigidbody on the object too
You have to tag the object "ob" that you want to register the collision with, most probably, I think what you are searching for is the collision of your player with object spawner so tag the player with "ob".

How to disable a script with void OnTriggerEnter2D?

So I have this script that disables my movement when I enter a certain area, how do I make my animation go from whatever animation they are in to my idle animation only when I enter the collider? Thanks!
using System.Collections.Generic;
using UnityEngine;
public class endLevel : MonoBehaviour
{
public void OnTriggerEnter2D(Collider2D collision)
{
GetComponent<CharacterController2d>().enabled = false;
Debug.Log("Level Cleared");
}
}
you have to specify that object is Player
first set your player Object Tag or Layer
set to "Player" and go to your script
if(collision.CompareTag("Player"))
or
int PlayerLayer;
void Start()
PlayerLayer = layer.NametoLayer("Player")
if(collision.gameObject.layer == PlayerLayer)
if collided gameObject is player. get player script's Animator to stop function.
collision.gameObject.GetComponent<Animator>().enabled = false;
"[...] make my animation go from whatever animation they are in to my idle animation only when I enter the collider[...]"
Use Animator.CrossFade. Example:
public void OnTriggerEnter2D(Collider2D collision)
{
GetComponent<Animator>().CrossFade("your_idle_state", 0.5f);
}
For performance reasons, I recommend caching the Animator reference in a private variable, initialized in Start(). If you are unsure if the object actually has an Animator Component, use TryGetComponent().

How to check if i`m touching something in Unity

I've got OnCollisionEnter2D function, but it say's only once, when i`m landing on ground, i want function that will return object name(or smthng like this) if i'm touching it, so if i'll stay on it it will say me about it not only once but every frame.
It's as simple as using the correct method OnCollisionStay2D which is called every frame while you are colliding with another object
Sent each frame where a collider on another object is touching this object's collider (2D physics only).
To be fair: Their example in that link is bullshit since it is for OnTriggerStay2D ^^
It could look like
private void OnCollisionStay2D(Collision2D collision)
{
Debug.Log($"I am touching {collision.gameObject.name}", this);
}
If instead you want to keep track of every touching object I would rather use something like
private HashSet<GameObject> _currentlyTouching = new HashSet<GameObject>();
private void OnCollisionEnter2D(Collision2D collision)
{
if(!_currentlyTouching.Contains(collision.gameObject))
{
_currentlyTouching.Add(collision.gameObject);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if(_currentlyTouching.Contains(collision.gameObject))
{
_currentlyTouching.Remove(collision.gameObject);
}
}
private void Update()
{
var logString = new StringBuilder("I am touching ");
foreach(var touchingObject in _currentlyTouching)
{
logString.Append(touchingObject.name).Append(" ");
}
Debug.Log(logString.ToString(), this);
}

Destroy particle system when initalised programmatically

I have a game with a player and an enemy.
I also have a particle system for when the player dies, like an explosion.
I have made this particle system a prefab so I can use it multiple times per level as someone might die a lot.
So in my enemy.cs script, attached to my enemy, I have:
public GameObject deathParticle;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.name == "Player" && !player.dead){
player.dead = true;
Instantiate(deathParticle, player.transform.position, player.transform.rotation);
player.animator.SetTrigger("Death");
}
}
So this plays my particle system when the player gets killed by an enemy. Now on my player script, I have this. This specific function gets played after the death animation:
public void RespawnPlayer()
{
Rigidbody2D playerBody = GetComponent<Rigidbody2D>();
playerBody.transform.position = spawnLocation.transform.position;
dead = false;
animator.Play("Idle");
Enemy enemy = FindObjectOfType<Enemy>();
Destroy(enemy.deathParticle);
}
This respawns the player like normal but in my project each time I die I have a death (clone) object which I don't want. The last 2 lines are meant to delete this but it doesn't.
I have also tried this which didn't work:
Enemy enemy = FindObjectOfType<Enemy>();
ParticleSystem deathParticles = enemy.GetComponent<ParticleSystem>();
Destroy(deathParticles);
There is no need to Instantiate and Destroy the death particle, that will create a lot of overhead, you can simply replay it when you want it to start and stop it, when you dont need it
ParticleSystem deathParticleSystem;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticleSystem.time = 0;
deathParticleSystem.Play();
}
public void RespawnPlayer()
{
//rest of the code
deathParticleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
or you can enable and disable the gameObject associated with your particle prefab
public GameObject deathParticlePrefab;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticlePrefab.SetActive(true);
}
public void RespawnPlayer()
{
//rest of the code
deathParticlePrefab.SetActive(false);
}
You could always create a new script and assign it to the prefab that destroys it after a certain amount of time:
using UnityEngine;
using System.Collections;
public class destroyOverTime : MonoBehaviour {
public float lifeTime;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
lifeTime -= Time.deltaTime;
if(lifeTime <= 0f)
{
Destroy(gameObject);
}
}
}
So in this case you would assign this to your deathParticle. This script is useful in a multitude of scenarios if you're instantiating objects so that you don't have a load of unnecessary objects.

Categories