I created a script that lets the player open a door with the button E when the camera's box collider collides with the door's rigid body. When I test it, the door doesn't close, and I get this error:
Coroutine couldn't be started because the the game object 'Door
(Closed)' is inactive!
Here is the code for the Door script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Door : MonoBehaviour
{
public GameObject door_closed, door_opened, intDot;
public AudioSource open, close;
public bool opened;
void OnTriggerStay(Collider other)
{
if (other.CompareTag("MainCamera"))
{
if (opened == false)
{
intDot.SetActive(true);
if (Input.GetKeyDown(KeyCode.E))
{
door_closed.SetActive(false);
door_opened.SetActive(true);
intDot.SetActive(false);
//open.Play();
StartCoroutine(repeat());
opened = true;
}
}
}
}
void OnTriggerExit(Collider other)
{
if (other.CompareTag("MainCamera"))
{
intDot.SetActive(false);
}
}
IEnumerator repeat()
{
yield return new WaitForSeconds(4.0f);
opened = false;
door_closed.SetActive(true);
door_opened.SetActive(false);
//close.Play();
}
}
I tried activating the door at the start but still doesn't work. Everything looks perfect to me.
Related
so everything seems to be running as far as the AI switching different States, however when it gets in range with the player the State freezes in attack and does not play any Attack Animation, I have created the AI with Bone Rigging, Im wondering if this may be affecting it, here is my script for calling the Animation and the script for one the animation has finished to go back to idleFollow state.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeleeWeapon : Weapon
{
[SerializeField] private float attackDelay = 1f;
private Collider2D damageAreaCollider2D;
private Animator animatorAttack;
private bool attacking;
private readonly int useMeleeWeapon = Animator.StringToHash(name:"UseMeleeWeapon");
private void Start()
{
damageAreaCollider2D = GetComponent<BoxCollider2D>();
animatorAttack = GetComponent<Animator>();
//animatorAttack.Play(useMeleeWeapon);
}
public override void UseWeapon()
{
StartCoroutine(routine: Attack());
}
/*protected override void Update()
{
base.Update();
// FlipMeleeWeapon();
}*/
private IEnumerator Attack()
{
if (attacking)
{
yield break;
}
// Attack
attacking = true;
damageAreaCollider2D.enabled = true;
animatorAttack.Play(useMeleeWeapon);
// Stop Attack
yield return new WaitForSeconds(attackDelay);
damageAreaCollider2D.enabled = false;
attacking = false;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "AI/Decisions/Attack Completed", fileName = "AttackCompleted")]
public class DecisionAttackCompleted : AIDecision
{
public override bool Decide(StateController controller)
{
return AttackCompleted(controller);
}
private bool AttackCompleted(StateController controller)
{
if (controller.CharacterWeapon.CurrentWeapon.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0).length
> controller.CharacterWeapon.CurrentWeapon.GetComponent<Animator>().GetCurrentAnimatorStateInfo(0).normalizedTime)
{
return true;
}
return false;
}
}
Ok I fixed the issue, I ended up placing this code into the WeaponMelee script, but now im dealing with a weird glitch where the AI keeps tring to face the left instead of the player when they are close to eachother. this has to do with the boxcollider2D so ive placed a capsulecollider2d inside of him and changed the script to capsulecollider2d as well. but the issue is still happening
private void OnTriggerEnter2D(Collider2D collision)
{
StartCoroutine(routine: Attack());
}
I have been making a 2D game in Unity. I'm trying to make a game over screen appear every time a ball touches the player. I also added advertisements to release it. I added Restart and Continue buttons. When you press continue, an ad shows and the game continues. When Restart is pressed, it resets the game and your score. Whenever I restart the game and then press continue, the ad is played, but the game does not continue.
Here is the collision script:
using UnityEngine;
public class hitDetect : MonoBehaviour
{
public GameObject menuContainer;
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log("HIT");
menuContainer.SetActive(true);
Time.timeScale = 0;
}
}
This is the script that restarts the game:
using UnityEngine;
using UnityEngine.SceneManagement;
public class RestartGame : MonoBehaviour
{
public void Restart()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
Time.timeScale = 1;
}
}
Here is the advertisement and continue script:
using UnityEngine;
using UnityEngine.Advertisements;
public class continueGame : MonoBehaviour, IUnityAdsListener
{
string placement = "rewardedVideo";
public GameObject menuContain;
private void Start()
{
Advertisement.AddListener(this);
Advertisement.Initialize("4006857", true);
}
public void Continue(string p)
{
Advertisement.Show(p);
}
public void OnUnityAdsReady(string placementId)
{
}
public void OnUnityAdsDidError(string message)
{
}
public void OnUnityAdsDidStart(string placementId)
{
}
public void OnUnityAdsDidFinish(string placementId, ShowResult showResult)
{
if(showResult == ShowResult.Finished)
{
menuContain.SetActive(false);
Time.timeScale = 1;
}
}
}
Once you call
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex)
a "new" scene is loaded and therefore anything currently existing is destroyed.
In continueGame you do
private void Start()
{
Advertisement.AddListener(this);
Advertisement.Initialize("4006857", true);
}
But you never remove that listener!
Thus the next time the Advertisement fires its event it is still trying to execute them of the now already destroyed continueGame instance.
Therefore you always should remove any listeners as soon as you don't need them anymore:
private void OnDestroy ()
{
Advertisement.RemoveListener(this);
}
so I’m trying to create a respawn system as a beginner, and everything seems to be working the first time but the second time it seems to be unbehaving. If anyone knows how to help me, I would appreciate it
LevelControl:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelControl : MonoBehaviour
{
public int index;
public string levelName;
public GameObject GameOverPanel;
public static LevelControl instance;
private void Awake()
{
if (instance == null)
{
DontDestroyOnLoad(gameObject);
instance = GetComponent<LevelControl>();
}
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
//Loading level with build index
SceneManager.LoadScene(index);
//Loading level with scene name
SceneManager.LoadScene(levelName);
//Restart level
//SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
public void LoadLevel1()
{
SceneManager.LoadScene("Game");
}
public GameObject GetGameOverScreen()
{
return GameOverPanel;
}
}
PlayerMovement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public CharacterController2D controller;
public float runSpeed = 40f;
float horizontalMove = 0f;
bool jump = false;
bool crouch = false;
// Update is called once per frame
void Update()
{
horizontalMove = Input.GetAxisRaw("Horizontal") * runSpeed;
if (Input.GetButtonDown("Jump"))
{
jump = true;
}
if (Input.GetButtonDown("Crouch"))
{
crouch = true;
}
else if (Input.GetButtonUp("Crouch"))
{
crouch = false;
}
}
void FixedUpdate()
{
// Move our character
controller.Move(horizontalMove * Time.fixedDeltaTime, crouch, jump);
jump = false;
//FindObjectOfType<GameManager>().EndGame();
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Enemy")
{
//Destroy(FindObjectOfType<CharacterController2D>().gameObject);
GameObject.Find("Player").SetActive(false);
LevelControl.instance.GetGameOverScreen().SetActive(true);
}
}
}
Error In Unity Video: https://imgur.com/a/Sr0YCWk
If your wondering what I'm trying to do, well, when the 2 colliders of the Player and Enemy collide, I want a restart button to pop up, and the Character to get destroyed, and after that restart the level as is.
You didn't provide much but I try to work with what we have.
In LevelController you have
private void Awake()
{
if (instance == null)
{
DontDestroyOnLoad(gameObject);
instance = GetComponent<LevelControl>();
}
}
First of all just use
instance = this;
;)
Then you are doing
LevelControl.instance.GetGameOverScreenn().SetActive(true);
I don't see your setup but probably GetGameOverScreenn might not exist anymore after the Scene reload while the instance still does due to the DontDestroyOnLoad.
Actually, why even use a Singleton here? If you reload the entire scene anyway you could just setup the references once via the Inspector and wouldn't have to worry about them later after scene changes...
Also
GameObject.Find("Player").SetActive(false);
seems odd .. isn't your PlayerController attached to the Player object anyway? You could just use
gameObject.SetActive(false);
Ok, Normally it would be easier just to do this:
if (collision.gameObject.tag == "Enemy")
{
//Destroy(FindObjectOfType<CharacterController2D>().gameObject);
gameObject.SetActive(false);
LevelControl.instance.GetGameOverScreen().SetActive(true);
But this will NOT work if you want to attach the script to any other gameobjects for any reason. If you are then first make a game object variable containing the player, like this:
public GameObject Player = GameObject.Find("Player");
Then say
Player.SetActive(false);
This creates a player gameobject which you can access by calling the variable.
As stated in the title unity does not see the animation attached to it through the code, which in turn, this animation I put in the inspector
My player has a BoxCollider2D with IsTrigger ticked, so that it takes the value and runs
I put a check (already in the code) for the presence of animation, but he says exactly that he does not see
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CrackedPlatformScript : MonoBehaviour
{
public AnimationClip destroyed;
private void OnTriggerEnter2D(Collider2D other)
{
if(other.gameObject.tag == "Player")
{
if(destroyed != null)
{
GetComponent<Animation>().Play(destroyed.name);
gameObject.GetComponent<BoxCollider2D>().enabled = false;
Destroy(gameObject,0.4f);
}
else
{
Debug.Log(destroyed.name);
}
}
}
}
I writing simple game on Unity (C#)
I have player and want to make the destroyer, that will destroy player.
I create prefab of destroyer. And next, I create Quad.
I have spawn script:
using UnityEngine;
using System.Collections;
public class SpawnScript : MonoBehaviour {
public GameObject[] obj;
public float spawnMin = 1f;
public float spawnMax = 2f;
// Use this for initialization
void Start () {
Spawn();
}
void Spawn()
{
Instantiate(obj[Random.Range(0, obj.GetLength(0))], transform.position, Quaternion.identity);
Invoke("Spawn", Random.Range(spawnMin, spawnMax));
}
}
Also I write DestroyerScript:
using UnityEngine;
using System.Collections;
public class DestroyerScript : MonoBehaviour {
void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player")
{
Application.LoadLevel(1);
return;
}
if (other.gameObject.transform.parent)
{
Destroy(other.gameObject.transform.parent.gameObject);
}
else
{
Destroy(other.gameObject);
}
}
}
My destroyer spawning, but when player get it, I don't have Game Over screen.
Add rigid body to both player and "player destroyer" and then set onTriggerEnter on your player destroyer like so:
void OnTriggerEnter(Collider other) {
Destroy(other.gameObject);
}
For some fine tuning, you can do some checks if the other object is in fact the Destroyer (you can compare the tag or something, I won't go into too much detail now).
EDIT: Uncheck "isTrigger" on your BoxColliders and try this:
void OnCollisionEnter (Collision col)
{
Destroy(col.gameObject);
}