Unity C# How to move sphere - c#

I am completely new to Unity. I am having difficulty in building a FPS shooter. Here is my code in Ammo prefab:
public class Ammo : MonoBehaviour {
public GameObject obj ;
// Use this for initialization
void Start () {
obj= GameObject.FindGameObjectWithTag ("Player");
}
// Update is called once per frame
void Update () {
transform.Translate (obj.transform.forward* Time.deltaTime);
}
void OnCollision(Collider coll)
{
if (coll.tag != "Player")
Destroy (gameObject);
}
}
And in FPS:
public class FPS : MonoBehaviour {
public GameObject Ammo;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetButtonDown("Fire1"))
{
Instantiate(Ammo, transform.position,transform.rotation);
}
}
}
But when I shoot the sphere goes in random direction. (It goes up when I look forward). Is there anyone help me. I am absolutely new to Unity.

Bullet doesn't go in random direction. It depends on your player position. First of all you should take forward vector from players camera NOT FROM PLAYER. Because you want to shoot the direction you look at (thus the camera).

Related

How can I make it so that the player loses health when an enemy collides with a different object?

Here an image of what my game looks like so far so that you can get a better idea but I need it so that when one of the outer capsules touches the red box the player (middle capsule) loses health.
I have tried creating a new script which checks for collisions but I couldn't get it to work and am unsure where to go from here. Below is my code for how the health bar works and pressing the space bar reduces health for demonstration purposes.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PlayerHealth : MonoBehaviour
{
public float MaxHealth;
public Slider _slide;
private float currentHealth;
void Start()
{
currentHealth = MaxHealth;
_slide.maxValue = MaxHealth;
_slide.value = MaxHealth;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
TakeDamage(25f);
if(currentHealth <=0)
{
//move to game over
}
}
void TakeDamage(float Damage)
{
currentHealth = currentHealth - Damage;
_slide.value = currentHealth;
}
}
At one point I tried using
void Update()
{
(collision.collider.name == "Barrier");
TakeDamage(25f);
if(currentHealth <=0)
{
//move to game over
}
}
but realised this is completely wrong, as well as trying to add a box collider to the red "barrier" to aid this but it didn't fix anything.
Update 2:
Also tried changing it so that the enemies move towards the barrier and not the player and added the code:
private void OnTriggerEnter(Collider other) {
TakeDamage(25f);
if(currentHealth <=0)
{
//move to game over
}
}
which doesn't present any errors but rather just doesn't do anything. The enemy capsules just go through it and to the centre, with no health being lost.
You need to check for collisions using OnCollisionEnter3D and then use the TakeDamage function inside of it. Here is an example:
public class PlayerHealth: MonoBehaviour
{
void OnCollisionEnter3D(Collision3D col) //Check for collision
{
TakeDamage(25f);
}
}
Note that for this function to work, both objects need a 3d collider and a rigid body. If you don't want your character to fall, just set gravity to 0.

How do I make an instantiated object keep following my player after its instantiated?

I drew a little red animation thing for when my player gets hit. I have an arrow shooter in my level but my problem is the red damage effect instantiates where my player is at, but when my player moves the object stays in the player's old position. Like lets say my player is at x:10. The effect will spawn at x:10 but when I move to x:17 the effect will stay at x:10.
Here's my code
public int damagedealt;
public Player playerscript;
public GameObject RedDamage;
public Vector2 playerpos;
public GameObject player;
// Start is called before the first frame update
void Start()
{
playerscript = FindObjectOfType<Player>();
}
// Update is called once per frame
void Update()
{
playerpos = player.transform.position;
player = GameObject.FindGameObjectWithTag("Player");
transform.Translate(Vector2.right * speed * Time.deltaTime);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Player"))
{
playerscript.health -= damagedealt;
Instantiate(RedDamage, playerpos, transform.rotation);
Destroy(gameObject);
}
}
and if it's useful at all here's the damage effect script
{
public float duration;
// Start is called before the first frame update
void Start()
{
duration = .7f;
}
// Update is called once per frame
void Update()
{
duration -= Time.deltaTime;
if (duration <= .13f )
{
Destroy(gameObject);
}
}
}
You can either add a follow script to the object you would like to follow your player or you can child the object to the player. When an object is childed to another, its transform becomes relative to its parent. In your case, your instantiated object would move relative to your player.
As this seems like a temporary effect that is repeated multiple times, it might make sense to child an empty object for the sole purpose of spawning your effect there. Create an empty gameObject that is childed (meaning placed under in the scene hierarchy) to your player object. Make sure to set the position of this new empty object in a place where you would like to spawn your object.
Once you are happy with where the object is placed, you can alter your Instantiate slightly to fit the new approach.Instantiate has a few overloads to the method. The one I will use is as follows
public static Object Instantiate(Object original, Transform parent);
Instead of specifying a rotation, position, etc, you will specify the parent at which the object will be placed and childed to. Here is what the script would now look like
public int damagedealt;
public Player playerscript;
public GameObject RedDamage;
public Vector2 playerpos;
public GameObject player;
// serializing a field will expose it in the editor even if marked private
// while not allowing other scripts to access it
[SerializeField] private Transform DisplayDamageFeedback = null;
// Start is called before the first frame update
void Start()
{
playerscript = FindObjectOfType<Player>();
}
// Update is called once per frame
void Update()
{
playerpos = player.transform.position;
player = GameObject.FindGameObjectWithTag("Player");
transform.Translate(Vector2.right * speed * Time.deltaTime);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Player"))
{
playerscript.health -= damagedealt;
Instantiate(RedDamage, DisplayDamageFeedback);
Destroy(gameObject);
}
}
Make sure to assign the reference to DamageFeedback in the inspector to the empty gameObject you created earlier. If you need help on any of the steps just let me know.
Try something like this.
in the effects' 'Update' script:
GameObject player = GameObject.FindGameObjectWithTag("Player");;
public void MoveGameObject()
{
transform.position = new Vector3(player.transfom.position.x,player.transform.position.y,player.transform.position.z);
}
This means that every Update, the player object is found, and the effect's position is set to match the players.
See the following link for Unity's example of position:
https://docs.unity3d.com/ScriptReference/Transform-position.html

destroying gameObject in both cases in Unity

I have written a code where when the player is not being rendered in camera it should be destroyed but it is being destroyed even being rendered in camera, please see my below code;
using UnityEngine;
public class IfnotvisibleDestroy : MonoBehaviour
{
public SpriteRenderer re;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
public void Update()
{
if (re.isVisible)
{
Debug.Log(re.isVisible);
}
if(!re.isVisible)
{
Destroy(gameObject);
}
}
}
Do the destroy gameObject part inside the FixedUpdate function

How to transform position from one object to the current player position?

So i have this little particlesystem attached on my player so if he dies he explodes. But i cant simply attach the particlesystem under the player because if i destroy my player the childs of the gameobjects get destroyed as well. The animation runs if he dies but not on his current spot so some ideas for that? Maybe to transform the position to the current position of the player while he dies?
Here my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerdeath : MonoBehaviour
{
public ParticleSystem death_explosion;
// Start is called before the first frame update
void Start()
{
death_explosion.Stop();
}
// Update is called once per frame
void Update()
{
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "deathcube")
Destroy(gameObject);
Debug.Log("collision detected");
death_explosion.Play();
}
}
What you could do is create a prefab of the particle object and reference it inside your script like so:
public ParticleSystem death_explosion_Prefab;
And instead of attaching it to the Player as a child, instantiate it on collision:
void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "deathcube")
{
Debug.Log("collision detected");
Instantiate(death_explosion_Prefab, gameObject.transform.position, Quaternion.identity);
Destroy(gameObject);
}
}
got it :) --> add death_explosion.transform.position = GameObject.Find("player").transform.position;

Destroy particle system when initalised programmatically

I have a game with a player and an enemy.
I also have a particle system for when the player dies, like an explosion.
I have made this particle system a prefab so I can use it multiple times per level as someone might die a lot.
So in my enemy.cs script, attached to my enemy, I have:
public GameObject deathParticle;
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.name == "Player" && !player.dead){
player.dead = true;
Instantiate(deathParticle, player.transform.position, player.transform.rotation);
player.animator.SetTrigger("Death");
}
}
So this plays my particle system when the player gets killed by an enemy. Now on my player script, I have this. This specific function gets played after the death animation:
public void RespawnPlayer()
{
Rigidbody2D playerBody = GetComponent<Rigidbody2D>();
playerBody.transform.position = spawnLocation.transform.position;
dead = false;
animator.Play("Idle");
Enemy enemy = FindObjectOfType<Enemy>();
Destroy(enemy.deathParticle);
}
This respawns the player like normal but in my project each time I die I have a death (clone) object which I don't want. The last 2 lines are meant to delete this but it doesn't.
I have also tried this which didn't work:
Enemy enemy = FindObjectOfType<Enemy>();
ParticleSystem deathParticles = enemy.GetComponent<ParticleSystem>();
Destroy(deathParticles);
There is no need to Instantiate and Destroy the death particle, that will create a lot of overhead, you can simply replay it when you want it to start and stop it, when you dont need it
ParticleSystem deathParticleSystem;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticleSystem.time = 0;
deathParticleSystem.Play();
}
public void RespawnPlayer()
{
//rest of the code
deathParticleSystem.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
}
or you can enable and disable the gameObject associated with your particle prefab
public GameObject deathParticlePrefab;
private void OnTriggerEnter2D(Collider2D collision)
{
#rest of the code
deathParticlePrefab.SetActive(true);
}
public void RespawnPlayer()
{
//rest of the code
deathParticlePrefab.SetActive(false);
}
You could always create a new script and assign it to the prefab that destroys it after a certain amount of time:
using UnityEngine;
using System.Collections;
public class destroyOverTime : MonoBehaviour {
public float lifeTime;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
lifeTime -= Time.deltaTime;
if(lifeTime <= 0f)
{
Destroy(gameObject);
}
}
}
So in this case you would assign this to your deathParticle. This script is useful in a multitude of scenarios if you're instantiating objects so that you don't have a load of unnecessary objects.

Categories