I'm trying to make a 2D sprite flip in a 3D scene, whenever the camera reaches an Y rotation of 180.
I can't get it to work, even though the TEST debug text shows whenever it reaches 180.
This is the code I have:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotate_enemy : MonoBehaviour {
[SerializeField] SpriteRenderer spriteRenderer;
public bool flipX;
void Update()
{
float fYRot = Camera.main.transform.eulerAngles.y;
if (fYRot >= 180)
{
Debug.Log("TESTING");
spriteRenderer.flipX = true;
}
else
{
spriteRenderer.flipX = false;
}
}
}
I have a similiar script, that instead changes rotation based on velocity (the direction to which the character is going), and that script works just fine.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Sprite_flip : MonoBehaviour {
[SerializeField] SpriteRenderer spriteRenderer;
public bool flipX;
Vector3 pos, velocity;
void Awake()
{
pos = transform.position;
}
// Update is called once per frame
void Update()
{
velocity = (transform.position - pos) / Time.deltaTime;
pos = transform.position;
if (velocity.x >= 0)
{
spriteRenderer.flipX = true;
}
else
{
spriteRenderer.flipX = false;
}
}
}
Anyone who might have an idea why the Rotate_Enemy script isn't doing what I want to achieve? Tried to find solutions but I couldn't make any of them work, so there must be something I don't understand. Super grateful for any help! :)
Related
I have a problem with writing a function that throws spawned ball by pressing a button.
So far, i could only instantiate the ball and it is affected by gravity.
I can not wrap my head arround, how in my code should i add a force to push it with some force. Right now it just plops in front of a player.
I tried to fiddle with .AddForce() on a ball rigidbody2D and still nothing.
I would greatly appreciate if someone could take a look at the code and guide me into some directcion on where to AddForce for ball to make it move?
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerControl : MonoBehaviour
{
[Header("Player Atributes")]
[SerializeField] float runSpeed = 10f;
Vector2 moveInput;
Rigidbody2D playerRigidbody2D;
[Header("Ball Settings")]
public bool playerHasABall = false;
[SerializeField] GameObject ball;
[SerializeField] Transform ballSpawn;
void Start()
{
playerRigidbody2D = GetComponent<Rigidbody2D>();
}
void Update()
{
Run();
FlipSprite();
}
void OnMove(InputValue value)
{
moveInput = value.Get<Vector2>();
}
void OnFire(InputValue value)
{
if(!playerHasABall) {return;}
Instantiate(ball, ballSpawn.position, transform.rotation);
playerHasABall = false;
}
void Run()
{
Vector2 playerVelocity = new Vector2 (moveInput.x * runSpeed, playerRigidbody2D.velocity.y);
playerRigidbody2D.velocity = playerVelocity;
}
void FlipSprite()
{
bool playerHasHorizontalSpeed = Mathf.Abs(playerRigidbody2D.velocity.x) > Mathf.Epsilon;
if (playerHasHorizontalSpeed)
{
transform.localScale = new Vector2 (Mathf.Sign(playerRigidbody2D.velocity.x), 1f);
}
}
//Ball picking up script. It destroys the ball with a tag "Ball" and sets a bool playerHasABall to true
private void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Ball")
{
Destroy(other.gameObject);
playerHasABall = true;
}
}
}
So, i manage to fiddle with the .AddForce() method once again and i came up with a solution to my problem.
My OnFire script looks like this:
void OnFire(InputValue value)
{
if(!playerHasABall) {return;}
Instantiate(ball, ballSpawn.position, transform.rotation);
playerHasABall = false;
}
No change here. I made another script called "BallBehaviour.cs" and added it to the ball with a code like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallBehaviour : MonoBehaviour
{
[SerializeField] float ballForce = 20f;
PlayerControl player;
void Start()
{
player = FindObjectOfType<PlayerControl>();
Throw();
}
public void Throw()
{
GetComponent<Rigidbody2D>().AddForce(player.transform.localScale * ballForce, ForceMode2D.Impulse);
}
}
Basically, the method Throw() tells the ball to check the direction the player is facing and then multiply it by ballForce. Then, it uses the ForceMode2d.Impulse method to apply calculated force to the ball for a second and it works on left or right direction.
Thanks Jkimishere for a nudge in a propper direction!
You might need a variable to check if the player is facing right/left.
If the player is, just add force to the ball depending on the direction.
if(!playerHasABall) {return;}
Instantiate(ball,
ballSpawn.position,
transform.rotation);
//Check which way the player is facing and add forrce to that direction.
//Adding a FacingRight boolean might help.....
playerHasABall = false;
As soon as I add my camera follow script to the camera, my player can no longer be controlled.No error is displayed.As soon as I start the game the x and y position changes to negative during the game.As soon as I delete the follow script everything works again.Can someone help me please?
Here the scripts:
Follow Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
[SerializeField]
public GameObject followObject;
public void Update()
{
if (!followObject)
{
followObject = GameObject.FindGameObjectWithTag("Player");
}
transform.position = new Vector3(followObject.transform.position.x, followObject.transform.position.y, -10);
}
}
PlayerController:
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.Profiling.Memory.Experimental;
using UnityEngine;
using UnityEngine.UI;
public class PlayerController : MonoBehaviour
{
[Range(0, .3f)] [SerializeField] private float m_MovementSmoothing = .05f;
public static PlayerController PC;
public float runSpeed = 200;
public float jumpSpeed;
private bool isJumping;
private float move;
private Vector3 m_Velocity = Vector3.zero;
void Update()
{
move = Input.GetAxis("Horizontal");
// Move the character by finding the target velocity
Vector3 targetVelocity = new Vector2(move * 10f, rb.velocity.y);
// And then smoothing it out and applying it to the character
rb.velocity = Vector3.SmoothDamp(rb.velocity, targetVelocity, ref m_Velocity, m_MovementSmoothing);
if (move < 0)
{
transform.eulerAngles = new Vector3(0, 180, 0);
}else if(move > 0)
{
transform.eulerAngles = new Vector3(0, 0, 0);
}
if(Input.GetButtonDown("Jump") && !isJumping)
{
rb.AddForce(new Vector2(0f, jumpSpeed));
isJumping = true;
}
private void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.CompareTag("Ground"))
{
isJumping = false;
}
if (other.gameObject.CompareTag("MGround"))
{
this.transform.parent = other.transform;
isJumping = false;
}
}
private void OnCollisionExit2D(Collision2D other)
{
if (other.gameObject.CompareTag("MGround"))
{
this.transform.parent = null;
isJumping = true;
}
}
}
Try this:
Put it on camera game object
and put player game object to player window in the inspector
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraFollow : MonoBehaviour
{
[SerializeField]
public Transform player;
public void Update()
{
transform.position = new Vector3(player.position.x, player.position.y);
}
}
You´re scripts are incomplete and I could not reproduce your error. Did you copy/paste the full source?
I cleaned them up anyway and they work perfectly for me.
Here is what I did.
Camera Follow
No Changes
Player Controller
Add a Private "RigidBody2D rb" to the script since it was missing but you were
using it in Update().
Move Collision Methods out of Update
Add closing brackets.
I'm using this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class CollisionPlayer : MonoBehaviour
{
public bool alreadyDied = false;
public GameObject player;
public float timeDeath;
public ParticleSystem particles;
public GameObject explosionGO;
private SpriteRenderer sr;
private BoxCollider2D bc;
private PlayerController walkScript;
void Start()
{
sr = GetComponent<SpriteRenderer>();
bc = GetComponent<BoxCollider2D>();
walkScript = GetComponent<PlayerController>();
}
void OnCollisionEnter2D (Collision2D collide)
{
if (collide.gameObject.CompareTag("Dead"))
{
Instantiate(particles, player.transform.position, Quaternion.identity);
Instantiate(explosionGO, player.transform.position, Quaternion.identity);
CinemachineShake.Instance.ShakeCamera(30f, .1f);
alreadyDied = true;
}
}
void Update()
{
if(alreadyDied == true)
{
timeDeath -= Time.deltaTime;
sr.enabled = false;
bc.enabled = false;
walkScript.enabled = false;
}
if(timeDeath <= 0)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
}
This is the bullet's code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LeftBulletScript : MonoBehaviour
{
// Start is called before the first frame update
public float speed;
public float destructionLeftTime;
public ParticleSystem particles;
private GameObject thisGameObject;
void Start()
{
thisGameObject = this.gameObject;
Destroy(gameObject, destructionLeftTime);
}
void Update()
{
transform.Translate(Vector2.left * speed * Time.deltaTime);
if(destructionLeftTime > 0.05f)
{
destructionLeftTime -= Time.deltaTime;
}
else
{
Instantiate(particles, thisGameObject.transform.position, Quaternion.identity);
}
}
}
This code should spawn some particles and a sound effect when the player gets hit by something with tag "Dead". But that does not happen. I have a box collider 2D on both the bullet (that should kill me) and the player. My Rigidbody2D is dynamic on the player with z freezed. The bullet does not have a rigidbody. I made sure that the bullet actually has the tag "Dead", spelled the exact same way as the way I wrote on the script. The weirdest thing is that I used this code on another game and nothing changed (just the name of a script). Both the player and the bullet are on the same layer. Anyone could tell me what could have happened?
Hello i want to create a group of the same prefab following the player in my game. I already got the prefab intantiation to follow the player but when there is more than one they just follow the exact same path on top of each other. is there a way where they can follow the player but act like a bunch of bees moving?
Thanks!
This is the script on my prefab:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class KillerMovement : MonoBehaviour {
public GameObject player;
void FixedUpdate()
{
Vector2 toTarget = player.transform.position - transform.position;
float speed = 0.5f;
transform.Translate(toTarget * speed * Time.deltaTime);
}
}
The best solution depends on you game logic, but you may consider having a delay before starting following (you can tweak the delay depending on the position you want to the particular object to assume in the trail.
using System.Collections;
using UnityEngine;
public class Follower : MonoBehaviour
{
public GameObject player;
public float delay = 0f;
public float speed = .5f;
bool isReady = false;
void Start()
{
StartFollowing();
}
public void StartFollowing()
{
StartCoroutine(WaitThenFollow(delay));
}
IEnumerator WaitThenFollow(float delay)
{
yield return new WaitForSeconds(delay);
isReady = true;
Debug.Log(gameObject.name);
Debug.Log(Time.time);
}
void FixedUpdate()
{
if (isReady && player != null)
{
Vector2 toTarget = player.transform.position - transform.position;
transform.Translate(toTarget * speed * Time.deltaTime);
}
}
}
I've called StartFollowing in the Start method for you to test the code. You should call this method whenever approrpiate in your game logic.
I'm trying to make enemies follow my player when the player enters the radius area of an enemy, but make the enemy stop following when my bullet hits object or enters radiusArea.
See my gif for more detail:
Gif
script:
using UnityEngine;
using System.Collections;
public class FlyEnemyMove : MonoBehaviour
{
public float moveSpeed;
public float playerRange;
public LayerMask playerLayer;
public bool playerInRange;
PlayerController thePlayer;
// Use this for initialization
void Start()
{
thePlayer = FindObjectOfType<PlayerController>();
}
// Update is called once per frame
void Update()
{
flip();
playerInRange = Physics2D.OverlapCircle(transform.position, playerRange, playerLayer);
if (playerInRange)
{
transform.position = Vector3.MoveTowards(transform.position, thePlayer.transform.position, moveSpeed * Time.deltaTime);
//Debug.Log(transform.position.y);
}
//Debug.Log(playerInRange);
}
void OnDrawGizmosSelected()
{
Gizmos.DrawWireSphere(transform.position, playerRange);
}
void flip()
{
if (thePlayer.transform.position.x < transform.position.x)
{
transform.localScale = new Vector3(0.2377247f, 0.2377247f, 0.2377247f);
}
else
{
transform.localScale = new Vector3(-0.2377247f, 0.2377247f, 0.2377247f);
}
}
}
I hope someone can help me :(
Physics2D.OverlapCircle detects only the collider with the lowest z value (if multiple are in range). So you either need to change the z values so the player has the lowest or you need to work with Physics2D.OverlapCircleAll and check the list to find the player. Or you could change your layers so only the player itself is on that specific layer you feed into the overlap test.