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.
Related
So I'm developing my first game in Unity currently (following a series by Mister Taft on YouTube called "Make a game like Zelda using Unity and C#" and just finished the 19th video).
I've currently got a "Log" enemy and am working on a knockback feature. I've followed the way that it is approached in the series is by creating a state machine that changes the Log's state to "stagger" for a couple of seconds, then return it to "idle" so it can change itself to "walk."
Whenever I hit the Log, however, it gets stuck in the stagger state and drifts without stopping until it hits a collider (note it doesn't change back to idle/walk even when it does hit the collider). If I can hit the Log correctly, sometimes, the player will actually also drift in the opposite direction.
Relevant code:
public class Log : Enemy {
private Rigidbody2D myRigidBody;
public Transform target;
public float chaseRadius;
public float attackRadius;
public Transform homePosition;
public Animator anim;
// Use this for initialization
void Start () {
currentState = EnemyState.idle;
myRigidBody = GetComponent<Rigidbody2D> ();
anim = GetComponent<Animator> ();
target = GameObject.FindWithTag ("Player").transform;
}
// FixedUpdate is called by physics.
void FixedUpdate () {
CheckDistance ();
}
//Log finds and walks towards Player.
void CheckDistance(){
if (Vector3.Distance (target.position, transform.position) <= chaseRadius && Vector3.Distance (target.position, transform.position) > attackRadius
&& currentState != EnemyState.stagger)
{
Vector3 temp = Vector3.MoveTowards (transform.position, target.position, moveSpeed * Time.deltaTime);
myRigidBody.MovePosition (temp);
ChangeState (EnemyState.walk);
}
}
private void ChangeState(EnemyState newState){
if (currentState != newState)
{
currentState = newState;
}
}
}
public class Knockback : MonoBehaviour {
public float thrust;
public float knockTime;
private void OnTriggerEnter2D(Collider2D other){
if (other.gameObject.CompareTag ("breakable"))
{
other.GetComponent<Pot>().Smash();
}
if(other.gameObject.CompareTag("enemy"))
{
Rigidbody2D enemy = other.GetComponent<Rigidbody2D>();
if (enemy != null)
{
enemy.GetComponent<Enemy> ().currentState = EnemyState.stagger;
Vector2 difference = enemy.transform.position - transform.position;
difference = difference.normalized * thrust;
enemy.AddForce (difference, ForceMode2D.Impulse);
StartCoroutine (KnockCo (enemy));
}
}
}
private IEnumerator KnockCo(Rigidbody2D enemy){
if (enemy != null)
{
yield return new WaitForSeconds (knockTime);
enemy.velocity = Vector2.zero;
enemy.GetComponent<Enemy>().currentState = EnemyState.idle;
}
}
}
public enum EnemyState{
idle,
walk,
attack,
stagger
}
public class Enemy : MonoBehaviour {
public EnemyState currentState;
public int enemyHealth;
public string enemyName;
public int baseAttack;
public float moveSpeed;
}
I've tried to add an else statement after the void CheckDistance in Log.cs, but that resulted in the Log having jittery movement and jumping back along its path. I'm at a loss. Any help would be greatly appreciated!
So I am trying to make the player a child to the moving platform which is being moved by looking for waypoints and going to them. But when I make the player collide with the platform the collision enter is not detecting the player thus not making the player stay on it, it instead glides off.enter image description here
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movePlatform : MonoBehaviour
{
public GameObject[] waypoints;
float rotSpeed;
int current = 0;
public float speed;
float WPradius = 1;
private GameObject target = null;
private Vector3 offset;
public GameObject Player;
CharacterController controller;
void Start()
{
controller = GetComponent<CharacterController>();
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Player")
{
//This will make the player a child of the Obstacle
controller.transform.parent = other.gameObject.transform;
}
}
void OnTriggerExit(Collider other)
{
controller.transform.parent = null;
}
// Update is called once per frame
void Update()
{
if (Vector3.Distance(waypoints[current].transform.position, transform.position) < WPradius)
{
current++;
if (current >= waypoints.Length)
{
current = 0;
}
}
transform.position = Vector3.MoveTowards(transform.position, waypoints[current].transform.position, Time.deltaTime * speed);
}
}
This will not make the player a child of the platform:
controller.transform.parent = other.gameObject.transform;
Because here controller is the CharacterController instance, and other refers to the player collider. So they both refers to the player transform in the end.
Replace it by something like
other.transform.parent = transform;
or
controller.transform.parent = transform;
(Here, transform refers to the platform transform.)
If the OnTriggerEnter() is not detecting, check if your collider has isTrigger enabled. Or change the method to OnCollisionEnter().
If you are making a 2D game, switch these methods to the 2D version (=> OnCollisionEnter2D or OnTriggerEnter2D).
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.
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.
Not sure why, I've done this sort of this a bunch of times, but this is giving me some issues. Making a project for Game AI, I have a whole bunch of stuff already done, now just making some turrets that if the player is in a certain range it will fire, which I have already. The turret fires the bullet and then for some reason they just start destroying themselves and they don't go towards my player. Wondering if anyone on here can help, thanks in advance!
Some details you may need to know:
I have a Base, a Gun nose and a Gun for my turret. My Gun has a GunLook.cs script that makes it look at the player (so when they shoot it should go towards them), I'm not sure if that has anything to do with why I'm having these issues, but I'll post that code as well just incase
How my Hierchy for my turret is
Turret_AI (Base)
Gun (child of Turret_AI)
bulletSpawn (child of Gun)
Gun_Nose (child of turret_AI)
bulletSpawn is an empty GameObject I created in hopes to solve my problem. I set it just off the Gun so that it wouldn't just collide with gun and destroy itself (what I thought it might be doing, but not correct).
That should be all the info needed, if anyone needs more I will be checking this every 2 seconds so let me know and I will get back to you with quick response.
TurretScript.cs
(I did set the GameObject to Player in Unity, before anyone asks)
using UnityEngine;
using System.Collections;
public class TurretScript : MonoBehaviour {
[SerializeField]
public GameObject Bullet;
public float distance = 3.0f;
public float secondsBetweenShots = 0.75f;
public GameObject followThis;
private Transform target;
private float timeStamp = 0.0f;
void Start () {
target = followThis.transform;
}
void Fire() {
Instantiate(Bullet, transform.position , transform.rotation);
Debug.Log ("FIRE");
}
void Update () {
if (Time.time >= timeStamp && (target.position - target.position).magnitude < distance) {
Fire();
timeStamp = Time.time + secondsBetweenShots;
}
}
}
GunLook.cs
// C#
using System;
using UnityEngine;
public class GunLook : MonoBehaviour
{
public Transform target;
void Update()
{
if(target != null)
{
transform.LookAt(target);
}
}
}
BulletBehavior.cs
using UnityEngine;
using System.Collections;
public class BulletBehavior : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (rigidbody.velocity.magnitude <= 0.5)
Destroy (gameObject);
}
void OnCollisionEnter(Collision collision)
{
if (collision.collider)
{
if(collision.gameObject.tag == "Enemy" || collision.gameObject.tag == "EnemyProjectile")
{
Physics.IgnoreCollision(rigidbody.collider,collision.collider);
//Debug.Log ("Enemy");
}
if(collision.gameObject.tag == "SolidObject")
{
Destroy(gameObject);
}
if(collision.gameObject.tag == "Player")
{
Destroy(gameObject);
}
}
}
}
You're never moving your bullet.
public class BulletBehavior : MonoBehaviour
{
private const float DefaultSpeed = 1.0f;
private float startTime;
public Vector3 destination;
public Vector3 origin;
public float? speed;
public void Start()
{
speed = speed ?? DefaultSpeed;
startTime = Time.time;
}
public void Update()
{
float fracJourney = (Time.time - startTime) * speed.GetValueOrDefault();
this.transform.position = Vector3.Lerp (origin, destination, fracJourney);
}
}
Then call it like so:
void Fire()
{
GameObject bullet = (GameObject)Instantiate(Bullet, transform.position , transform.rotation);
BulletBehavior behavior = bullet.GetComponent<BulletBehavior>();
behavior.origin = this.transform.position;
behavior.destination = target.transform.position;
Debug.Log ("FIRE");
}
Note: If you're trying to mix this approach with trying to use physics to move the bullet you may end up with strange results.