I'm working with unity and have problem with audio. Here is scenario when user click on button, Object falls on ground and destroy. When click on button sound effect of object falling is play. And destroy, Object is instantiate again then same click sound effect is play again. But when one object is falling and does not collide at this time user click again that button sound play again. I want that when one object is complete destroy than again click happen and sound is play.
Code CubeScript:
public class Cube : MonoBehaviour {
Rigidbody2D body;
void Start () {
body = GetComponent<Rigidbody2D>();
body.isKinematic = true;
}
}
Code ColliderScript:
public class Ground : MonoBehaviour {
private Button bt;
public GameObject cube;
public AudioSource source;
public AudioClip clip;
void Start () {
bt = GameObject.FindGameObjectWithTag ("Button").GetComponent<Button> ();
bt.onClick.AddListener (() => Fall ());
}
void OnCollisionEnter2D(Collision2D col) {
Destroy (col.gameObject);
Instantiate (cube,new Vector3(0f,4.19f,0f),Quaternion.identity);
}
public void Fall(){
GameObject.FindGameObjectWithTag ("Player").GetComponent<Rigidbody2D> ().isKinematic = false;
source.PlayOneShot(clip);
}
}
void OnCollisionEnter2D(Collision2D col) {
Destroy (col.gameObject);
Instantiate (cube,new Vector3(0f,4.19f,0f),Quaternion.identity);
isFalling = false; // here
}
private bool isFalling = false; // here
public void Fall()
{
GameObject.FindGameObjectWithTag ("Player").GetComponent<Rigidbody2D> ().isKinematic = false;
if(isFalling == false){
source.PlayOneShot(clip);
isFalling = true; // here
}
}
Pretty much when you press, it calls Fall, if nothing is falling down, the sound happens. On Collision, the isFalling is reset. Tho I am not entirely sure about your logic.
Related
I have a game that I want a restart button to appear if you die (The game object destroys itself).
This is what I have. This is the script attached to the button:
public GameObject Player;
public GameObject Button;
bool player;
public void RestartGame(){
SceneManager.LoadScene("SampleScene");
}
void Start(){
player = true;
}
void Update(){
if (!Player){
player = false;
}
if(player == true) {
Button.SetActive(false);
}
if(player == false){
Button.SetActive(true);
}
}
And this is the code attached to the object that gets deleted:
void OnTriggerEnter(Collider other)
{
Destroy(gameObject);
}
When it starts the Button is disabled but when I die nothing appears. I have tried many things like checking if it is == null and all of that stuff but it still doesn't work. My goal is to make the restart button appear once the object is destroyed.
From what I understand you are checking if player get destroyed or not. However you are destroying trigger.
There must be a tag on player object use that. On your trigger object use this code. Pass player and button on inspector.
public GameObject Player;
Public GameObject Button;
void OnTriggerEnter(Collider other)
{
if (other.gameobject.comparetag("Player"))
{
Destroy (Player);
Button.SetActive(true);
}
}
For this to work both objects player and trigger must have colliders
and at least one of them must have rigidbody , and player tag must be Player
Okay, the plan is simple.
My plan is to make a simple AI that record every player.positions, and then follow the player by using those positions. So the AI will always be some steps behind the player. But when the player stops moving the AI should collide with player and then the player dies.
So my problem is when the player has been chased down by the AI, but it always runs out of position before the enemy AI is ever able to touch the player...
I used Queue for making a list of position, this was recommended by someone after I tried with List<>.
Here's a video showing the problem
public Transform player;
public Transform ghostAI;
public bool recording;
public bool playing;
Queue<Vector2> playerPositions;
public bool playerLeftRadius;
void Start()
{
playerPositions = new Queue<Vector2>();
}
// Update is called once per frame
void Update()
{
if (playerLeftRadius == true)
{
StartGhost();
}
Debug.Log(playerPositions.Count);
}
private void FixedUpdate()
{
if (playing == true)
{
PlayGhost();
}
else
{
Record();
}
}
void Record()
{
recording = true;
playerPositions.Enqueue(player.transform.position);
}
void PlayGhost()
{
ghostAI.transform.position = playerPositions.Dequeue();
}
public void StartGhost()
{
playing = true;
}
public void StopGhost()
{
playing = false;
}
private void OnTriggerExit2D(Collider2D other)
{
Debug.Log("Player leaved the zone");
playerLeftRadius = true;
}
How do improve it so it will be able to touch the player?
At the moment the player touch the zone, method OnTriggerExit2D() is called. Then, method PlayGhost() is called and Record() is stoped. So, the ghost can't record player.positions after player out zone.
You can remove else in method FixedUpdate() to fix it.
private void FixedUpdate()
{
if (playing == true)
{
PlayGhost();
}
Record();
}
so I'm making a 2d platform. My level is made up of a multiple platforms that are all part of a prefab. I want to make it so when my player presses a key (in this case 'E') inside of a collider2d the platform above the player is destroyed and the box resting on the platform falls down.
I've got the detection working for when 'E' is pressed inside of the trigger but can't figure out how to destroy just the single platform in the prefab.
Any help would be appreciated!
public class SwitchController : MonoBehaviour
{
public Collider2D switchCollider;
public Rigidbody2D player;
void Start()
{
switchCollider = GetComponent<Collider2D>();
}
private void OnTriggerStay2D(Collider2D col)
{
// var player = col.GetComponent<PlayerController>();
var actionBtn = PlayerController.action;
if (player)
{
Debug.Log("Collided");
if (Input.GetKeyDown(KeyCode.E))
{
actionBtn = true;
Debug.Log("Action Pressed");
}
}
}
}
If possible, the simplest solution would be to store the platform via the inspector (of the prefab).
Then you would destroy the game-object when needed, like so:
public class SwitchController : MonoBehaviour {
// ...
public GameObject targetPlatform;
private void OnTriggerStay2D(Collider2D col) {
// ...
Destroy(targetPlatform); // Destroy the platform.
}
}
Or, you can raycast upwards from the player
public class SwitchController : MonoBehaviour {
public Collider2D switchCollider;
public Rigidbody2D player;
[SerializeField, Tooltip("The layer mask of the platforms.")]
public LayerMask platformLayerMask;
void Start() {
switchCollider = GetComponent<Collider2D>();
}
private void OnTriggerStay2D(Collider2D col) {
var actionBtn = PlayerController.action;
if (player) {
if (Input.GetKeyDown(KeyCode.E)) {
actionBtn = true;
// Raycast upwards from the player's location.
// (Raycast will ignore everything but those with the same layermask as 'platformPlayerMask')
RaycastHit2D hit = Physics2D.Raycast(player.transform.position, Vector2.up, Mathf.Infinity, platformLayerMask);
if (hit.collider != null) {
// Destroy what it hits.
Destroy(hit.transform.gameObject);
}
}
}
}
}
Compared to the first solution, this solution is more dynamic.
You just have to set the Layers of the platforms in the inspector.
I'm learning about raycasting in unity3d and facing a audio problem. What I'm doing is there is a Main Camera which attached with a script called NewCast. That Main Camera cast a ray to the cube which has a component called box collider. Ray casting is working fine, when looking at that cube. I'm playing a sound. It means when camera looking at that object ray is cast to the cube. But why audio is playing multiple times. I want to play that audio only one time, when i look at that object and repeat this procedure again and again. Package link.
Code:
public class NewCast : MonoBehaviour
{
private RaycastHit hit;
bool playAudio1;
[SerializeField]
private AudioSource source;
[SerializeField]
private AudioClip clip1;
private void Start()
{
source.clip = clip1;
playAudio1 = true;
}
private void Update()
{
if (Physics.Raycast(transform.position, transform.forward, out hit,9f))
{
if (hit.collider.gameObject.name == "Cube")
{
playAudio1 = false;
if (!playAudio1)
{
source.Play();
if (!source.isPlaying)
{
playAudio1 = true;
}
}
}
}
}
}
Everytime the collider is hitting, you're setting playAudio1 to false so the next condition is always true and so the sound will always play...
if (Physics.Raycast(transform.position, transform.forward, out hit,9f))
{
if (hit.collider.gameObject.name == "Cube"){
if (!source.isPlaying){
source.Play();
}
}
}
If you want to play only ONCE per look to object :
public class NewCast : MonoBehaviour
{
private RaycastHit hit;
bool soundPlayed = false;
[SerializeField]
private AudioSource source;
[SerializeField]
private AudioClip clip1;
private void Start()
{
source.clip = clip1;
}
private void Update(){
if(Physics.Raycast(transform.position, transform.forward, out hit,9f)){
if (!soundPlayed && hit.collider.gameObject.name == "Cube"){
if (!source.isPlaying){
source.Play();
soundPlayed = true;
}
}
}else{
if(soundPlayed) soundPlayed = false;
}
}
}
It's sometime since I used Unity, but AudioSource in unity is set to automatically loop. Check the script which has the AudioSource and make sure you uncheck "is looping".
See the Unity Documentation
So am guesing that if you add this to your Start() function you will be ok
private void Start()
{
source.clip = clip1;
source.loop=false;//only plays the once and stops
playAudio1 = true;
}
I need to make an image pop up when the player has died or crashed but i do not know how to do it, i'm trying to make a game in unity using c#
but i have made a code that will tell show the user an image before they start (tap to start image) and all i want to do is display another one that tell to user to start again
does the code have to be similar to this or do i have to start from scratch?
public class StartScreenScript : MonoBehaviour {
static bool sawOnce = false;
// Use this for initialization
void Start () {
if(!sawOnce) {
GetComponent<SpriteRenderer>().enabled = true;
Time.timeScale = 0;
}
sawOnce = true;
}
// Update is called once per frame
void Update () {
if(Time.timeScale==0 && (Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButtonDown(0)) ) {
Time.timeScale = 1;
GetComponent<SpriteRenderer>().enabled = false;
}
}
}
this code show the an image telling the user to tap the screen and the image then goes away until the user closes the game then comes back on however i want to display a "you are dead image" every time the player dies can someone please help me
p.s this is for a 2d game
Well one way to do it would be using Unity3D's GUI.DrawTexture that given a texture draws it at a given position. Here is a sample call to the method.
GUI.DrawTexture(new Rect(leftAnchor, topAnchor, textureWidth, textureHeight), textureSource);
This is my approach and it works in most cases:
Create a GameObject that will work as a dead screen. Apply a sprite
or whatever telling the user to click to restart.
Add the previous GameObject to the PlayerController so he can
instantiate it.
When the player is dead call PlayerController.ShowDeadScreen()
When the user clicks inside DeadScreen GameObject it will call your
PlayerController.PlayAgain function and destroy itself. So you must handle everything
the game need to be restarted.
PlayerController example code
public class PlayerController : MonoBehaviour {
public GameObject deadScreen;
void Start() { }
void Update() { }
public void ShowDeadScreen()
{
// show DeadScreen GameObject on the center of the screen
GameObject go = Instantiate(deadScreen, new Vector(0, 0, 0), Quaternation.Identity) as GameObject;
go.playerController = this;
}
public void PlayAgain()
{
// handle game restart
}
}
DeadScreen example code
public class DeadScreen : MonoBehaviour {
public PlayerController playerController;
void Start() { }
void Update() { }
void OnMouseDown()
{
// when user clicks inside this GameObject start the game again
playerController.PlayAgain();
Destroy(this.gameObject);
}
}