cant work out what code is needed to change scene - c#

I have created the scenes and I want it to change scenes on death so the code should go under public override void Death():
public class player : Mover
{
private void FixedUpdate()
{
float x = Input.GetAxisRaw("Horizontal");
float y = Input.GetAxisRaw("Vertical");
UpdateMotor(new Vector3(x, y, 0));
}
public override void Death()
{
(need code here)
}
}

the code will be
SceneManager.LoadScene("OtherSceneName", LoadSceneMode.Additive);
Replace "OtherSceneName" with the scene you want to change to and choose a scene loading mode that suits your needs.

Related

FixedUpdate slightly fired up even if scene is paused with Time.timeScale = 0f

I'm a newbie in unity & c# . The FixedUpdate function does some Rigidbody action (here pushing the cube over the z axis)
However the scene works fine in development (cube starts at z = 0 )
The problem is in build , the cube starts at certain distance means z = 5 or 6
According to my understanding , I believe this is caused due to FixedUpdate being fired for some milli seconds before it notice Time.timeScale = 0f in PauseGame function
And when it notice this it behave as expected.
But then on Restart function when being called up (called by a button) using SceneManager.LoadScene function cube starts with z= 0 in build.
clip at development and clip with bug at build
where did I go wrong, thanks in advance.
image of bug at build, cube starts at certain position
image of development which working fine as expected cube starts at z = 0
public class GameController : MonoBehaviour
{
public GameObject tapToStart;
private void Start()
{
tapToStart.SetActive(true);
PauseGame();
}
private void Update()
{
StartGame();
}
public void Restart()
{
SceneManager.LoadScene("Game");
}
public void PauseGame()
{
Time.timeScale = 0f;
}
public void StartGame()
{
tapToStart.SetActive(false);
Time.timeScale = 1f;
}
}
public class PlayerScript : MonoBehaviour
{
public new Rigidbody rigidbody;
public float force;
private void Update(){}
private void FixedUpdate()
{
rigidbody.AddForce(0, 0, force * Time.deltaTime);
}
}
You are correct! FixedUpdate is called at relatively'fixed' intervals. It doesn't matter if something is done in your other code and you need it to get updated immediately. FixedUpdate will just keep pressing on at a a regular interval.
You can verify your suspicions by placing the line:
rigidbody.AddForce(0, 0, force * Time.deltaTime);
Inside your Update() function.
Now, onto the solution. I suggest that create place the following code in your currently empty Update() function:
if(Time.timeScale = 0f){
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
}
Now, as soon as you press the pause button, it will be detected on the next frame of Update() and the object will be frozen. This will likely occur even before FixedUpdate is called. Of course, if you want to 'restore' the velocity and angular velocity when you unpause, you will need to store that data, and then set it back up when you unpause the game.
The issue has been solved .. I can't pause on start,
need to create a Boolean in PlayerScript.
public class PlayerScript : MonoBehaviour
{
public new Rigidbody rigidbody;
public float force;
public bool isGameStart; // this Boolean
private void Update(){}
private void FixedUpdate()
{
if (isGameStart)
{
rigidbody.AddForce(0, 0, force * Time.deltaTime);
}
}
}
and using that bool value , we need to use rigidbody component.
and in StartGame function in GameController we must assign true to that bool value
public class GameController : MonoBehaviour
{
public GameObject tapToStart;
public PlayerScript playerScript;
private void Start()
{
tapToStart.SetActive(true);
PauseGame();
}
private void Update()
{
StartGame();
}
public void Restart()
{
SceneManager.LoadScene("Game");
}
public void PauseGame()
{
Time.timeScale = 0f;
}
public void StartGame()
{
tapToStart.SetActive(false);
Time.timeScale = 1f;
playerScript.isGameStart = true;
}
}
this worked for me , this solution was given by a Youtuber "Unity city".. credits to him.

Building a camera transition for switching rooms

I'm trying to create a Zelda type camera that changes position after you reach a trigger point.
this is the code for the camera movement
public class CameraMovement : MonoBehaviour {
public Transform target;
public float smoothing;
public Vector2 maxPosition;
public Vector2 minPosition;
void LateUpdate()
{
if (transform.position != target.position)
{
Vector3 targetPosition = new Vector3(target.position.x, target.position.y, transform.position.z);
targetPosition.x = Mathf.Clamp(targetPosition.x, minPosition.x, maxPosition.x);
targetPosition.y = Mathf.Clamp(targetPosition.y, minPosition.y, maxPosition.y);
transform.position = Vector3.Lerp(transform.position, targetPosition, smoothing);
}
}
}
and this is the code for the room transition
public class RoomMove : MonoBehaviour
{
public Vector2 cameraChange;
public Vector3 playerChange;
private CameraMovement cam;
// Start is called before the first frame update
void Start()
{
cam = Camera.main.GetComponent<CameraMovement> ();
}
// Update is called once per frame
void Update()
{
}
private void OnTriggerEnter2D(Collider2D other)
{
if(other.CompareTag("Player"))
{
cam.minPosition += cameraChange;
cam.maxPosition += cameraChange;
other.transform.position += playerChange;
}
}
}
I've already tried to look up the answer in google and I found something similar but it did not work for me.
This is a little difficult due to the lack of details, info, and desire.
First make sure your setup is correct.
Does the object with RoomMove on it have a 2D collider marked trigger?
Does player have the "Player" tag on it?
Does the main camera have the movement script with the target variable set to the instance of the player? (Not a prefab, from the hierarchy)
Double check all of these first.
What you have here leads me to believe that all of your levels are side by side in one scene correct?
You could try removing the clamping and simply give each room an empty transform in the middle and when you hit the transition change the camera's target.

Why when adding a Rigidbody to a door and Is Kinematic is enabled true on the door open automatic when running the game?

The idea is to add a Rigidbody to some doors and use Is Kinematic so when a npc/enemy will walk through the doors they will open/close.
But when I'm running the game the doors open automatic without anything triggering it.
Maybe I didn't add the Rigidbody to the right place in the door the right object/child ?
A screenshot of a door one of few I have:
Each Collision (1) to Collision(11) have attached a Box Collider. On each one the Is Trigger is unchecked !
The Horizontal_Doors_Kit have attached a Box Collider and the Is Trigger is check enabled ! And also attached to it a script Hori Door Manager:
using UnityEngine;
using System.Collections;
public class HoriDoorManager : MonoBehaviour
{
public DoorHori door1;
public DoorHori door2;
public static bool doorLockState;
void OnTriggerEnter()
{
if (doorLockState == false)
{
if (door1 != null)
{
door1.OpenDoor();
}
if (door2 != null)
{
door2.OpenDoor();
}
}
}
}
Wall_Door_Long_01 have attached a Mesh Renderer.
Door_Left and Door_Right have a Mesh Renderer , Audio Source , a script and a Box Collider where Is Trigger unchecked !
The script is attached to door left and to door right:
using UnityEngine;
using System.Collections;
public class DoorHori : MonoBehaviour {
public float translateValue;
public float easeTime;
public OTween.EaseType ease;
public float waitTime;
private Vector3 StartlocalPos;
private Vector3 endlocalPos;
private void Start(){
StartlocalPos = transform.localPosition;
gameObject.isStatic = false;
}
public void OpenDoor(){
OTween.ValueTo( gameObject,ease,0.0f,-translateValue,easeTime,0.0f,"StartOpen","UpdateOpenDoor","EndOpen");
GetComponent<AudioSource>().Play();
}
private void UpdateOpenDoor(float f){
Vector3 pos = transform.TransformDirection( new Vector3( 1,0,0));
transform.localPosition = StartlocalPos + pos*f;
}
private void UpdateCloseDoor(float f){
Vector3 pos = transform.TransformDirection( new Vector3( -f,0,0)) ;
transform.localPosition = endlocalPos-pos;
}
private void EndOpen(){
endlocalPos = transform.localPosition ;
StartCoroutine( WaitToClose());
}
private IEnumerator WaitToClose(){
yield return new WaitForSeconds(waitTime);
OTween.ValueTo( gameObject,ease,0.0f,translateValue,easeTime,0.0f,"StartClose","UpdateCloseDoor","EndClose");
GetComponent<AudioSource>().Play();
}
}
When I added the Rigidbody it was to the parent Wall_Door_Long_01 also added to it a Box Collider.
Then when running the game the door/s opened automatic without anything to trigger it like a npc enemy character.
The doors are working fine and when I'm moving my FPSController through the doors they open and close fine. My problem is when a npc/character that move automatic when the game start through the doors I could not find to make the character walking fine with a Rigidbody so I decided to add a Rigidbody to the doors. But now the doors open automatic when running the game.
This script I'm using to check if the doors are locked or unlocked using the public static doorLockState variable:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DoorsLockManager : MonoBehaviour
{
public bool locked;
public bool lockStateRealTime = false;
public Renderer rend;
private Shader unlitcolor;
private GameObject[] doorPlanes;
private void Start()
{
doorPlanes = GameObject.FindGameObjectsWithTag("DoorPlane");
ChangeColors(new Color32(255, 0, 0, 255), new Color32(0, 255, 0, 255));
}
private void ChangeMaterialSettings()
{
unlitcolor = Shader.Find("Unlit/Color");
rend.material.shader = unlitcolor;
rend.material.SetFloat("_Metallic", 1);
}
private void ChangeColors(Color32 lockedColor, Color32 unlockedColor)
{
for (int i = 0; i < doorPlanes.Length; i++)
{
rend = doorPlanes[i].GetComponent<Renderer>();
ChangeMaterialSettings();
if (locked)
{
HoriDoorManager.doorLockState = true;
rend.material.color = lockedColor;
}
else
{
HoriDoorManager.doorLockState = false;
rend.material.color = unlockedColor;
}
}
}
// Update is called once per frame
void Update()
{
if (lockStateRealTime)
{
ChangeColors(new Color32(255, 0, 0, 255), new Color32(0, 255, 0, 255));
lockStateRealTime = false;
}
}
}
I think your problem is in your collision detection for the door. A rigidbody on the door itself should have no effect.
First: Your OnTriggerEnterfunction does not have the correct pattern to work since it is missing the Collider collidername parameter.
private void OnTriggerEnter(Collider other)
{
}
You can call you collider whatever you want (IntelliSense defaults to other) but your method has to have a parameter like this to be recognized as a OnTriggerEnterfunction by Unity.
Second: You never check if the object triggering your collider is actually the object you want to open the door.
Try tagging your player and NPCs with some kind of tag like Playeror something like that.
Then you check if the colliding object has this tag attatched to it and only then you open the door.
Something like this:
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
//do stuff
}
if(other.CompareTag("NPC"))
{
//do other stuff
}
}
Or if there is only one action for every tag:
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player") || other.CompareTag("NPC"))
{
//do stuff
}
}
Note that for OnTriggerEnterto detect a collision one or more objects colliding need a RigidBodycomponent attached to them, so you are not entirely wrong with that.

other.transform.SetParent messes up with scale of my player

So i was working on to make my moving platform stable for my player.
I used void OnCollisionEnter2D(Collision2D other)' inside platform container script and used 'player.transform.SetParent(plankTranform);'
But setting player transform to be child of platform transform messes up with scale of player.
My best guess is that platform's scale property is being transferred into player's transform.scale. Is there way to just set tranform.position of platform as parent of player's transform.position?
Using player.transform.SetParent(plankTranform); automatically sets tranform 3 properties i.e (position,scale,rotation) to child object. I dnt really want to deal with scale and rotation in this case
public class BrickMoveVErtical : MonoBehaviour {
public Vector3 positionOne;
public Vector3 positiontwo;
public Vector3 nextposition;
public Transform plankTranform;
/*Empty object is already made on unity editor and its parent of
platform(Plank) and other
empty object "pointB". Point "B" is already mapped on editor and platform
is set to go from its original pos to point B */
public Transform positionBTransform;
public float speed;
// Use this for initialization
void Start () {
positionOne = plankTranform.localPosition;
positiontwo = positionBTransform.localPosition;
nextposition = positiontwo;
}
// Update is called once per frame
void Update () {
move();
}
private void move() {
plankTranform.localPosition = Vector3.MoveTowards(plankTranform.localPosition,nextposition,Time.deltaTime*speed);
if(Vector3.Distance(plankTranform.localPosition,nextposition)<0.1)
{ changeMovementPlank(); }
}
void changeMovementPlank() {
nextposition = nextposition != positionOne ? positionOne : positiontwo;
}
void OnCollisionEnter2D(Collision2D other)
{ if(other.gameObject.tag=="Player")
{
other.transform.SetParent(plankTranform);
}
}
void OnCollisionExit2D(Collision2D other)
{
other.transform.SetParent(null);
}
}
Use SetParent(parent, true);
worldPositionStays
If true, the parent-relative position, scale and rotation are modified such that the object keeps the same world space position, rotation and scale as before.

Throwing an object at an arch in 2D using C#

I am trying to create a 2D game where the user throws a bomb at an arch from point A(which is a fixed point) to point B(which will change constantly). My trouble comes in when I am trying to make the bomb move towards the target location, I cannot seem to get it to go where I touch. I also cannot get it to go there in an arch. Is there anyone that can assist me in solving this problem. Other help that I have researched is for a 3D situation and I have trouble converting it into a 2D model.
Below are the two scripts that are being used together.
public class PlayerController : MonoBehaviour {
public int[] distanceToThrow;
public int[] bombToThrow;
public GameObject bomb;
public Transform throwOrigin;
public Vector2 throwSpeed;
public float gravity;
//public Transform throwPointPos;
public Vector2 throwDestination;
public float flightSpeed;
public float throwTimer;
public float throwResetTimer;
public float landingTime;
public Vector2 touchPos;
private BombController theBomb;
private Rigidbody2D bombRB;
//private Camera theCamera;
// Use this for initialization
void Start () {
//theCamera = FindObjectOfType<Camera>();
theBomb = FindObjectOfType<BombController>();
bombRB = theBomb.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if (throwTimer > 0)
{
throwTimer -= Time.deltaTime;
// Using a single touch as control - Letholor
}
else if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
touchPos = new Vector2(touch.position.x, touch.position.y);
Debug.Log("You are touching at position: " + touchPos);
/* Ray ray = Camera.main.ScreenPointToRay(touchPos);
RaycastHit hitResult;
Physics.Raycast(ray, out hitResult);*/
Vector2 throwDestination = touchPos;
Debug.Log("Throw destination is " + throwDestination);
SendBomb(throwDestination);
}
}
public void SendBomb(Vector2 throwDestination) {
if (throwTimer > 0)
{
Debug.Log("Cooling down.");
return;
}
throwTimer = throwResetTimer;
Debug.Log("Throwing bomb to " + throwDestination);
//Instantiate(bomb, throwOrigin.position, throwOrigin.rotation);
GameObject newBomb = Instantiate(bomb, throwOrigin.position, throwOrigin.rotation);
newBomb.GetComponent<BombController>().SetThrowDestination(touchPos - throwDestination);
}
}
public class BombController : MonoBehaviour {
public int bombTimer;
public float explosionRadius;
public int resetTimer;
public bool exploded;
public Animation anim;
private Rigidbody2D bombRigidbody;
public float bombSpeed;
public float gravity;
private PlayerController thePlayer;
// Use this for initialization
void Start () {
bombRigidbody = GetComponent<Rigidbody2D>();
thePlayer = FindObjectOfType<PlayerController>();
}
// Update is called once per frame
void Update () {
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground" || collision.gameObject.tag == "Bomb")
{
bombRigidbody.velocity = new Vector2(0, 0);
}
}
public void Detonate()
{
anim.Play("explode");
exploded = true;
}
public void SetThrowDestination(Vector2 throwDestination)
{
bombRigidbody.velocity = throwDestination * bombSpeed;
}
}
Things to check:
Make sure your Rigidbody2D has its Gravity Scale property set to 1 and the Body Type to Dynamic.
Check you give a value to Edit -> Project Settings -> Physics 2D -> Gravity -> Y (it's in Newtons, so -9.8 sounds about right).
Since velocity should not be edited, use AddForce to make it move in the direction you want.
Make sure the direction vector is calculated as destination - origin (delta position), or in your case throwDestination - throwOrigin. Any multipliers should be applied to the direction vector (e.g. bombSpeed).
Remove any direct manipulation to velocity and let the physics engine do its thing.
All of that should make the object move in the direction you want. If it doesn't, then there's probably a problem with one of the vectors or maybe the bombSpeed is too low ("Add zeroes until it breaks"). Try setting the vector values manually and make sure they're not being modified by any other section of the code.

Categories

Resources