Show and hide animation for a hand - c#

So . I work at a 2d game in unity and I have some problems with some mechanics and i really need some help from you guys. All I want to do is to make my character hand to stop and grab a object. When I press E the animation of the hand start and have a collider for each frame, in case that the hand collide with a closer object, the animation to stop at that frame. I have a week since I try to figure it out. If you want to help me we can do it on discord. I will put the codes here, maybe the reason that I can't to what I want to do is very clear and I dont see it.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class showHide : MonoBehaviour
{
[SerializeField]
GameObject hand;
private Animator freeze;
public bool touch = false;
private bool ok = true;
// Start is called before the first frame update
void Start()
{
freeze = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.E) && ok == true)
{
freeze.Play("Follower");
StartCoroutine(show());
}
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "box")
{
StartCoroutine(colliderShow());
}
}
private IEnumerator show()
{
ok = false;
hand.SetActive(true);
yield return new WaitForSeconds(4f);
hand.SetActive(false);
ok = true;
}
private IEnumerator colliderShow()
{
touch = true;
print(touch);
yield return new WaitForSeconds(4f);
touch = false;
print(touch);
}
private void FreezeAniamtion()
{
freeze.speed = 0f;
StartCoroutine(waitTime());
}
private IEnumerator waitTime()
{
yield return new WaitForSeconds(0f);
freeze.speed = 1f;
}
}
This is the code that activate and deactivate my hand object , including the animation .
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class facingScript : MonoBehaviour
{
private SpriteRenderer render;
private Camera mainCam;
private Vector3 mousePos;
private Animator aniHand;
public bool atinge;
void Start()
{
mainCam = Camera.main;
render = GetComponent<SpriteRenderer>();
aniHand = GetComponent<Animator>();
gameObject.SetActive(false);
}
// Update is called once per frame
void Update()
{
mousePos = Input.mousePosition;
mousePos = mainCam.ScreenToWorldPoint(
new Vector3(mousePos.x, mousePos.y, mainCam.transform.position.z - transform.position.z)
);
Vector3 rotation = mousePos - transform.position;
if (rotation.x > 0)
render.flipY = true;
else
render.flipY = false;
if (atinge == false)
aniHand.speed = 1f;
Debug.Log(aniHand.speed);
}
// Collision with objects
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "box")
{
atinge = true;
aniHand.speed = 0f;
StartCoroutine(freezingTime());
}
}
private IEnumerator freezingTime()
{
yield return new WaitForSeconds(4f);
atinge = false;
}
// No collision with any object
private void FreezeAnimation()
{
aniHand.speed = 0f;
StartCoroutine(waitTime());
}
private IEnumerator waitTime()
{
yield return new WaitForSeconds(0f);
aniHand.speed = 1f;
}
}
This is the hand component script . When the hand don't collide with anything the object is deactivated . The FreezeAnimation() is a event at the last frame. I tryed to do a collider animation for the showHide component that will be exact with the hand animation collider for each frame to check if the hand collide in the showHide script and if it collide to have a 4 seconds of waiting with the hand at that position.
I really tryed my best but I really can't figure it out.

Related

Clones not using animator / enabled / disabled functions?

I'm trying to make my enemy freeze when it gets in contact with an ice projectile. Everything works no errors except the animator doesn't play the animations and the script doesn't get enabled / disabled.
I've tried script = GetComponent(); and anim = gameObject.GetComponent(); too for that section. And for the set active ive tried script.enabled script.setactive ect ect. None of it works. I think this might have to do with the get component but IDK. These are on instantiated prefabs btw.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyHealth : MonoBehaviour
{
public float health;
public float freezeTime;
public Animator anim;
public Enemy script;
// Start is called before the first frame update
IEnumerator Wait(){
yield return new WaitForSeconds (freezeTime);
Debug.Log("waiting over");
}
void Start()
{
anim = gameObject.GetComponent<Animator>();
script = gameObject.GetComponent<Enemy>();
}
// Update is called once per frame
void Update()
{
if(health <= 0){
Dead();
}
}
void OnTriggerEnter2D(Collider2D other){
if(other.CompareTag("Harmful")){
Destroy(other.gameObject);
TakeDamage();
}
if(other.CompareTag("Freezing")){
anim.SetBool("IsFrozen", true);
Destroy(other.gameObject);
gameObject.GetComponent<Enemy>().enabled = false;
TakeDamage();
Debug.Log("waiting started");
StartCoroutine(Wait());
anim.SetBool("IsFrozen", false);
gameObject.GetComponent<Enemy>().enabled = true;
}
}
void TakeDamage(){
health -= 1f;
}
void Dead(){
Destroy(gameObject);
}
}
The problem was not in fact the animator or the scripts being set to false but it was actually because I had started a wait function but it started the wait function and immediately ran the code that was supposed to go after the wait function.
TLDR; waited but the code ran anyway.
If you want the completed working code here it is. The spacing is a little weird because of stackoverflow btw:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyHealth : MonoBehaviour
{
public float health;
public float freezeTime;
public Animator anim;
public Enemy script;
public Rigidbody2D rb;
public bool WaitOver;
// Start is called before the first frame update
IEnumerator Wait(){
yield return new WaitForSeconds (freezeTime);
WaitOver = true;
Debug.Log("waiting over");
}
void Start()
{
anim = gameObject.GetComponent<Animator>();
script = gameObject.GetComponent<Enemy>();
rb = gameObject.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if(health <= 0){
Dead();
}
if (WaitOver == true){
anim.SetBool("IsFrozen", false);
gameObject.GetComponent<Enemy>().enabled = true;
rb.isKinematic = false;
}
}
void OnTriggerEnter2D(Collider2D other){
if(other.CompareTag("Harmful")){
Destroy(other.gameObject);
TakeDamage();
}
if(other.CompareTag("Freezing")){
WaitOver = false;
anim.SetBool("IsFrozen", true);
rb.isKinematic = true;
Destroy(other.gameObject);
GetComponent<Enemy>().enabled = false;
TakeDamage();
Debug.Log("waiting started");
StartCoroutine(Wait());
}
}
void TakeDamage(){
health -= 1f;
}
void Dead(){
Destroy(gameObject);
}
}

Why the object with the script is start moving to the right after the referenced object finished moving?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VideoSettings : MonoBehaviour
{
public GameObject VideoAudioCube;
public float speed = 5f;
public float distanceToMove;
private bool keepMoving = true;
private Vector3 startPos;
private Vector3 endPos;
private bool moveBack = false;
private void Start()
{
startPos = VideoAudioCube.transform.position;
}
private void OnMouseDown()
{
if (keepMoving == true)
{
if (transform.GetComponentInChildren<TextMesh>().text == "Video")
{
StartCoroutine(MoveVideo());
}
keepMoving = false;
}
}
private IEnumerator MoveVideo()
{
endPos = VideoAudioCube.transform.position - VideoAudioCube.transform.right * distanceToMove;
if (moveBack == false)
{
while (VideoAudioCube.transform.position != endPos)
{
VideoAudioCube.transform.position =
Vector3.MoveTowards(VideoAudioCube.transform.position, endPos, Time.deltaTime * speed);
yield return null;
}
}
keepMoving = true;
moveBack = true;
}
}
In the screenshot the script is attached to the New Game cube. And the script is moving the empty GameObject parent :
The camera is facing the Buttons :
And this is after the GameObject moved for some reason I see that all the objects under Buttons start moving to the right :
It looks like the whole Buttons object is moving to the right but it's not it's only the children under buttons that move :
If I'm not using the script at all the children objects under Buttons will not move. I can't figure out what make the objects to start moving after the GameObject has finished moving.

null reference exception when accessing the variable from a prefab

I get the null reference exception error when trying to change the boolean to right (or left in that regard). My prefab should spawn at FirepointL.
My script does recognise the prefeb as it does not return a Null for finding the prefab (tested this).
I made sure my boolean was set to Public and i had dropped all the GameObjects to their designated places in the Inspector.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public GameObject bullet;
private Rigidbody2D myRigidbody;
private float speed = 15;
private bool facingRight;
private bool ground = false;
private float jump = 23;
// Start is called before the first frame update
void Start()
{
facingRight = true;
myRigidbody = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void FixedUpdate()
{
float horizontal = Input.GetAxis("Horizontal");
bullet = GameObject.FindGameObjectWithTag("Button");
Movement(horizontal);
Flip(horizontal);
if (Input.GetKey("w"))
{
if (ground)
{
GetComponent<Rigidbody2D>().velocity = new Vector2(GetComponent<Rigidbody2D>().velocity.x, jump);
}
}
// this is the part that returns the error
if (facingRight == true)
{
bullet.GetComponent<weapon>().right = true;
}
if (facingRight == false)
{
bullet.GetComponent<weapon>().right = false;
}
}
void OnTriggerEnter2D()
{
ground = true;
}
void OnTriggerExit2D()
{
ground = false;
}
private void Movement(float horizontal)
{
myRigidbody.velocity = new Vector2(horizontal * speed,myRigidbody.velocity.y);
}
private void Flip(float horizontal)
{
if (horizontal > 0 && !facingRight || horizontal < 0 && facingRight)
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class weapon : MonoBehaviour
{
// Start is called before the first frame update
public bool right;
public Transform firepointR;
public Transform firepointL;
public GameObject bulletPrefab;
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown("space"))
{
Debug.Log("It's the space key");
Shoot();
}
}
void Shoot()
{
if (right == true)
{
Instantiate(bulletPrefab, firepointR.position, firepointR.rotation);
}
if(right == false)
{
Instantiate(bulletPrefab, firepointL.position, firepointL.rotation);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class bullet : MonoBehaviour
{
public float speed = 20;
public Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
rb.velocity = transform.right * speed;
}
// Update is called once per frame
void Update()
{
}
}
Not sure if it's the exact issue, but there's a problem in PlayerMovement class. When you retrieve bullet you assume that an object with Button tag is present.
In my opinion, you should check for it with
// this is the part that returns the error
if (bullet && facingRight == true)
{
bullet.GetComponent<weapon>().right = true;
}
if (bullet && facingRight == false)
{
bullet.GetComponent<weapon>().right = false;
}
I think there is a problem with naming conventions. You are trying to find out a bullet whose name is "Button" but when you are instantiating the gameobject, it names it to something like Button(clone).
One solution that comes in my mind:
1st step:
Make a public static variable inside PlayerMovement script.
public static PlayerMovement Instance;
private void Awake()
{
Instance = this;
}
Set its value inside the awake function so that you can call it from anywhere.
2nd step:
I modified the shoot function.
void Shoot()
{
GameObject _firePosition = right == true ? firepointR : firepointL;
PlayerMovement.Instance.bullet = Instantiate(bulletPrefab, _firePosition.position, _firePosition.rotation); // we are setting the reference on runtime whenever we spawn a new bullet.
}
3rd Step:
Remove this line from PlayerMovement script as it is not needed now.
bullet = GameObject.FindGameObjectWithTag("Button");
PS: Code will not work if you don't follow step 3. Let me know if it helps. :)

OnCollisionEnter not working Unity3D

I'm trying to build a game where u need to dodge falling objects. I've made a hazard but it seems as if the hazard 'clone' is behaving diffrently.
I've made a collision script when the hazard hits the platform it needs to disappear. This works for the hazard object, but not the hazard clone objects that fall.
As u can see in the first screenshot, the red circled block behaves
like it use to. But the blue circled once (clones) fall right through
objects.
As u can see in the second screenshot, the red circled one is gone,
because it hit the platform. But still the blue once fall right
through.
Thanks in advance!
Below u will find the Collision script, below that is the Hazard Spawn script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HazardCollisionFunctions : MonoBehaviour {
#region Variables
//Public
//Private
#endregion
#region UnityFunctions
void Start()
{
}
void Update()
{
}
#endregion
private void OnCollisionEnter(Collision collision)
{
if(collision.gameObject.tag == "platform")
{
this.gameObject.SetActive(false);
}
if(collision.gameObject.tag == "Player")
{
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnHazards : MonoBehaviour {
#region Variables
//Public
//Private
[SerializeField]
public float minX = 0.0f;
[SerializeField]
public float maxX = 0.0f;
[SerializeField]
private GameObject[] hazards; //potential array of hazards
[SerializeField]
private float timeBetweenSpawns = 0.0f;
private bool canSpawn = false;
private int amountOfHazardsToSpawn = 0;
private int hazardToSpawn = 0;
#endregion
#region UnityFunctions
public void Start()
{
canSpawn = true; //Temp start
}
public void Update()
{
if(canSpawn == true)
{
StartCoroutine("GenerateHazard");
}
}
#endregion
private IEnumerator GenerateHazard()
{
canSpawn = false;
timeBetweenSpawns = Random.Range(0.5f, 2.0f); //Testing values
amountOfHazardsToSpawn = Random.Range(1, 5); //Testing values
for(int i = 0; i < amountOfHazardsToSpawn; i ++)
{
Vector3 spawnPos = new Vector3(Random.Range(minX, maxX), 8.0f, 0.0f); //Gen spawnpoint for the hazard
Instantiate(hazards[hazardToSpawn], spawnPos, Quaternion.identity); //Spawn the hazard
}
yield return new WaitForSeconds(timeBetweenSpawns);
canSpawn = true;
}
}
OnCollisionEnter
OnCollisionEnter takes Collision object as a parameter and it requires the isTrigger property of the attached Collider component to be FALSE.
void OnCollisionEnter(Collision collision)
{
foreach (ContactPoint contact in collision.contacts)
{
Debug.DrawRay(contact.point, contact.normal, Color.white);
}
}
OnTriggerEnter
OnTriggerEnter takes Collider object as a parameter and it requires the isTrigger property of the attached Collider component to be TRUE.
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("CheckPoint"))
{
Destroy(other.gameObject);
}
}
If you are instantiating the object from prefab, make sure that
prefab have required components (rigidbody/collider) and
properties to achieve the desired behaviour.
To detect Collision/Trigger, at least one of the object must have a
physics component (Rigidbody)
Rigidbody MUST be attached to the moving object.
Hope this helps :)

Player stuck on reactivation - not changing position to spawn

I'm writing a script controlling the enter and exit of a space ship in a 2D game.
The problem I'm running into is when exiting the ship, the player is reactivated, and you regain control, but it does not move the player to the empty gameobject I have attached to the ship, in a beginners attempt to move the player to the location of the ship, without ever destroying the player. The player simply spawns on its last known location prior to entering the ship, and I seem to be forced into that location, I can try to move, but its like I'm anchored to that position.
using UnityEngine;
using System.Collections;
public class SpaceShipActivator : MonoBehaviour
{
//Takeoff
public bool inRange;
public SpaceShipAtmosphereController SpaceShipAtmosphereController;
public PlayerController playerControl;
public GameObject Player;
public bool onBoard;
//End Takeoff
//Landing
public Transform Spawn;
public Transform landingGear2;
public Transform landingGear;
public LayerMask whatIsGround;
float groundRadius = 0.2f;
bool getIn;
bool landingGearStable;
bool landingGearStable2;
bool shipStable;
//EndLanding
Animator anim;
void Start()
{
anim = GetComponent<Animator>();
inRange = false;
SpaceShipAtmosphereController.enabled = false;
}
void Update()
{
AnimationUpdate();
//Launch
if (inRange && Input.GetButtonDown("Interact") && !onBoard)
{
LaunchShip();
}
//End launch
CheckLandingGear();
//Land
if(onBoard && Input.GetButtonDown("Roll"))
{
LandShip();
}
//End Land
}
//*********************************Functions**************************************
void LaunchShip()
{
anim.SetBool("Get In", true);
this.gameObject.tag = "Player";
SpaceShipAtmosphereController.enabled = true;
Player.tag = "InactivePlayer";
playerControl.enabled = false;
Player.SetActive(false);
onBoard = true;
}
void LandShip()
{
anim.SetBool("Get Out", true);
this.gameObject.tag = "InactivePlayer";
Player.tag = "Player";
playerControl.enabled = true;
SpaceShipAtmosphereController.enabled = false;
onBoard = false;
Player.SetActive(true);
Player.transform.position = Spawn.transform.position;
}
void CheckLandingGear()
{
//landingGear
landingGearStable = Physics2D.OverlapCircle(landingGear.position, groundRadius, whatIsGround);
landingGearStable2 = Physics2D.OverlapCircle(landingGear2.position, groundRadius, whatIsGround);
if (landingGearStable && landingGearStable2)
{
shipStable = true;
}
//End landingGear
}
void AnimationUpdate()
{
anim.SetBool("Get In", false);
anim.SetBool("Get Out", false);
}
//For launching ship
//IF player: inRange enter/exit boolean control.
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
//Debug.Log("houi p;gberf");
inRange = true;
}
}
void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
inRange = false;
}
}
//End IF player: inRange enter/exit boolean control.
}
On a side note, In that same script I've included landingGear, which is set to be two empty gameobjects that basically share Y and are spaced apart on X to check that the spaceship is not only grounded but level for the most part, so the animation doesn't look silly AND to check if the player can even get out. I know this isn't the question, but any input on it would be appreciated, but please don't feel obligated.
Thanks for the help

Categories