I cant delete an instantiated object in unity c# using Delete() - c#

So im coding a grappler from my game (code is from a tutorial with minor tweaks), and im trying to get an prefab instantiated on the top of the grapple that shows the top. its currently just an empty object with a sprite renderer. The grappling is working i just need to figure out how to delete the object when im not pressing the grapple button.
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class grapple : MonoBehaviour
{
public Camera mainCamera;
public LineRenderer _lineRenderer;
public DistanceJoint2D _distanceJoint;
public Transform target;
// Start is called before the first frame update
void Start()
{
_distanceJoint.enabled = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(1))
{
Vector2 mousePos = (Vector2)mainCamera.ScreenToWorldPoint(Input.mousePosition);
_lineRenderer.SetPosition(0, mousePos);
_lineRenderer.SetPosition(1, transform.position);
_distanceJoint.connectedAnchor = mousePos;
_distanceJoint.enabled = true;
_lineRenderer.enabled = true;
Instantiate(target, mousePos, Quaternion.identity);
//if (Input.GetKey("Space"))
//{
//transform.position = Vector2.MoveTowards(transform.position, target.position, 4 * Time.deltaTime);
//}
}
else if (Input.GetMouseButtonUp(1))
{
_distanceJoint.enabled = false;
_lineRenderer.enabled = false;
Destroy(target);
}
if (_distanceJoint.enabled)
{
_lineRenderer.SetPosition(1, transform.position);
}
}
}

Save instantiated object to a class member variable and use it for destroying later
GameObject _instantiatedObj;
void Update()
{
if (Input.GetMouseButtonDown(1))
{
Vector2 mousePos = (Vector2)mainCamera.ScreenToWorldPoint(Input.mousePosition);
_lineRenderer.SetPosition(0, mousePos);
_lineRenderer.SetPosition(1, transform.position);
_distanceJoint.connectedAnchor = mousePos;
_distanceJoint.enabled = true;
_lineRenderer.enabled = true;
_instantiatedObj = Instantiate(target, mousePos, Quaternion.identity);
//if (Input.GetKey("Space"))
//{
//transform.position = Vector2.MoveTowards(transform.position, target.position, 4 * Time.deltaTime);
//}
}
else if (Input.GetMouseButtonUp(1))
{
_distanceJoint.enabled = false;
_lineRenderer.enabled = false;
Destroy(_instantiatedObj);
}
if (_distanceJoint.enabled)
{
_lineRenderer.SetPosition(1, transform.position);
}
}

Related

How to add velocity to drag and drop?

So for my game I want to be able to pick up objects with my cursor and fling them. I got the drag and drop working on my own but I don't know how to make it fling the object if you throw it. If you try to fling it, the object just drops to the floor. Can someone help me? I tried looking online but I couldn't find a solution. Here's the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DragAndDropObjects : MonoBehaviour
{
public bool canDrag = true;
public bool isDragging;
GameObject player;
Rigidbody2D rb;
void Start()
{
rb = gameObject.GetComponent<Rigidbody2D>();
player = GameObject.Find("Player");
}
void OnMouseDown()
{
if(canDrag && player.GetComponent<Movement>().draggingEnabled)
{
if(!isDragging)
{
print("start dragging");
isDragging = true;
rb.gravityScale = 0f;
gameObject.GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.FreezeRotation;
player.GetComponent<Movement>().draggingObject = true;
GameObject[] heavyObjects = GameObject.FindGameObjectsWithTag("Heavy");
foreach (GameObject heavy in heavyObjects)
{
heavy.GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.None;
}
}
}
}
void OnMouseUp()
{
if(isDragging)
{
isDragging = false;
rb.gravityScale = 1f;
gameObject.GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.None;
player.GetComponent<Movement>().draggingObject = false;
print("stop dragging");
GameObject[] heavyObjects = GameObject.FindGameObjectsWithTag("Heavy");
foreach (GameObject heavy in heavyObjects)
{
heavy.GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.FreezePositionX;
}
}
}
void FixedUpdate()
{
Vector3 mousePos = Input.mousePosition;
mousePos = Camera.main.ScreenToWorldPoint(mousePos);
if(isDragging)
{
transform.position = Vector2.Lerp(transform.position, mousePos, 1f);
if (Input.GetAxis("Mouse ScrollWheel") > 0f )
{
gameObject.transform.Rotate(0, 0, 10f);
}
else if (Input.GetAxis("Mouse ScrollWheel") < 0f )
{
gameObject.transform.Rotate(0, 0, -10f);
}
}
}
}
If you have the answer please tell me! Thank you!
The way to do it would be to get the object velocity using RigidBody2D.velocity and add it to the object transform. You might also multiply the velocity by Time.deltaTime to make the flying process smoother.

Unity 2d : Objects being reinstantiated on scene reload after being destroyed

GOAL
So I'm creating a top down arena battler type game, and I want you to be able to restart the game by pressing R.
PROBLEM
When I press R, the whole scene resets as it should, except all the enemies that were previously instantiated (and then destroyed) are spawned again, all at once.
CODE
This is the enemy spawning code :
using System.Collections.Generic;
using UnityEngine;
public class EnemySpawn : MonoBehaviour
{
private float nextActionTime = 0.0f;
public float period = 5f;
public GameObject enemy;
void Update()
{
if (Time.time > nextActionTime ) {
nextActionTime += period;
GameObject clone = Instantiate(enemy, new Vector3(-1, 3, 0), Quaternion.identity);
clone.tag = "enemy";
}
}
}
This is the player code, responsible for restarting the scene (I have marked what I belive to be the relevantant sections with dashes) :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class PlayerController : MonoBehaviour
{
public Rigidbody2D rb;
public GameObject Shield;
public GameObject ShieldInstance;
public float moveSpeed = 4.3f;
public float sheildSpeed = 5f;
Vector2 movement;
AudioSource woop;
AudioSource waa;
----------------------------
GameObject[] enemies;
----------------------------
bool isDead = false;
void Start() {
woop = GameObject.Find("Main Camera/ShieldSFX").GetComponent<AudioSource>();
waa = GameObject.Find("Main Camera/DefeatSFX").GetComponent<AudioSource>();
}
void Update()
{
--------------------------------------------------------------
enemies = GameObject.FindGameObjectsWithTag("enemy");
--------------------------------------------------------------
movement.x = Input.GetAxisRaw("Horizontal");
movement.y = Input.GetAxisRaw("Vertical");
Vector3 mouseScreen = Input.mousePosition;
Vector3 mouse = Camera.main.ScreenToWorldPoint(mouseScreen);
transform.rotation = Quaternion.Euler(0, 0, Mathf.Atan2(mouse.y - transform.position.y, mouse.x - transform.position.x) * Mathf.Rad2Deg - 90);
if (Input.GetMouseButtonDown(0))
{
if (ShieldInstance != null || transform.GetChild(0).GetComponent<SpriteRenderer>().enabled == false) { return; }
woop.Play();
ShieldInstance = Instantiate(Shield, transform.position + transform.forward + transform.up, transform.rotation);
ShieldInstance.transform.parent = transform;
}
if (Input.GetMouseButtonUp(0))
{
if (ShieldInstance == null) { return; }
ShieldInstance.transform.parent = null;
ShieldInstance.GetComponent<ShieldController>().LaunchForward(sheildSpeed);
Destroy(ShieldInstance, 2.3f);
}
-------------------------------------------------------------------------------
if (Input.GetKey("r")) {
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
foreach (GameObject one in enemies) {
Destroy(one);
}
}
-------------------------------------------------------------------------------
}
void FixedUpdate() {
if (!isDead) {
rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
}
}
void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "enemy") {
waa.Play();
GameObject.Find("Canvas/gameover").GetComponent<Text>().enabled = true;
transform.GetChild(0).GetComponent<SpriteRenderer>().enabled = false;
GetComponent<PolygonCollider2D>().enabled = false;
}
}
}
And this is the enemy code :
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyFollow : MonoBehaviour
{
public float moveSpeed;
public ParticleSystem explode;
AudioSource boom;
Vector2 movement;
GameObject player;
Rigidbody2D rb;
SpriteRenderer sr;
PolygonCollider2D pc;
void Start() {
rb = GetComponent<Rigidbody2D>();
sr = transform.GetChild(0).GetComponent<SpriteRenderer>();
pc = GetComponent<PolygonCollider2D>();
player = GameObject.Find("Player");
boom = GameObject.Find("Main Camera/ExplodeSFX").GetComponent<AudioSource>();
}
void Update()
{
Vector2 difference = (player.transform.position - new Vector3(2, .5f, 0)) - transform.position;
if (difference.x > 0) {
movement.x = 1;
} else if (difference.x < 0){
movement.x = -1;
} else {
movement.x = 0;
}
if (difference.y > 0) {
movement.y = 1;
} else if (difference.y < 0){
movement.y = -1;
} else {
movement.y = 0;
}
rb.MovePosition(rb.position + movement * moveSpeed * Time.fixedDeltaTime);
}
void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "shield") {
StartCoroutine(ExplodeF());
}
}
private IEnumerator ExplodeF() {
explode.Play();
boom.Play();
sr.enabled = false;
pc.enabled = false;
yield return new WaitForSeconds(explode.main.startLifetime.constantMax);
Destroy(gameObject);
}
}
I would really appreciate any help!
If you want / need more details, just leave a comment :)
The problem is in Time.time, it is time since the start of the application, not since the start of the scene. So if you were in the game 30 secs, Time.time is 30 secs. If you reload the scene it is still 30 secs.
You have to count the time passed since entering the scene. Then it won't respawn all the enemies on scene reload.
When you restart the scene, everything is being destroyed and reset back except for the time.
The problem in your code is in the enemy spawner. Time.time returns the time passed since you started the game (and not since the scene was loaded). So, after the restart the if condition is true and the enemies are spawned.
If you want to count the time (in seconds) since the scene was loaded, what you can do is to add a variable in the enemy spawner class that would count the time
using System.Collections.Generic;
using UnityEngine;
public class EnemySpawn : MonoBehaviour
{
private float nextActionTime = 0.0f;
private float timeSinceStart = 0;
public float period = 5f;
public GameObject enemy;
void Update()
{
if (timeSinceStart > nextActionTime ) {
nextActionTime += period;
GameObject clone = Instantiate(enemy, new Vector3(-1, 3, 0), Quaternion.identity);
clone.tag = "enemy";
}
timeSinceStart += Time.deltaTime;
}
}
See Time.deltaTime

Grappling gun does not become a child of my player when picking it up

I followed a tutorial on Youtube and it was from a man named Dani. I also followed another one from someone called Dave / GameDevelopment on how to pick up objects in Unity 3D. I have ran into a problem where if I pick up a weapon that was on the ground by default it does not work. My gun floats in the air. I believe the main reason for this (don't quote me on this) is that the Gun is some how not becoming a child of the camera, which is what supposed to happen. Please fix and thanks.
This is my pick up script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PickUpScript : MonoBehaviour
{
public GrappleGun gunScript;
public Rigidbody rb;
public BoxCollider coll;
public Transform player, gunContainer, fpsCam;
public float pickUpRange;
public float dropForwardForce, dropUpwardForce;
public bool equipped;
public static bool slotFull;
private void Start()
{
if(!equipped)
{
gunScript.enabled = false;
rb.isKinematic = false;
coll.isTrigger = false;
}
if (equipped)
{
gunScript.enabled = true;
rb.isKinematic = true;
coll.isTrigger = true;
slotFull = true;
}
}
private void Update()
{
//equipped and e is pressed
Vector3 distanceToPlayer = player.position - transform.position;
if (!equipped && distanceToPlayer.magnitude <= pickUpRange && Input.GetKeyDown(KeyCode.E) && !slotFull) PickUp();
//Drop if equipped and q is pressed
if (equipped && Input.GetKeyDown(KeyCode.Q)) Drop();
}
private void PickUp()
{
equipped = true;
slotFull = true;
transform.SetParent(gunContainer);
transform.localPosition = Vector3.zero;
transform.localRotation = Quaternion.Euler(Vector3.zero);
transform.localScale = Vector3.one;
//Enable rb and km and coll = trigger
rb.isKinematic = true;
coll.isTrigger = true;
//Enable Script
gunScript.enabled = true;
}
private void Drop()
{
equipped = false;
slotFull = false;
transform.SetParent(null);
//Enable rb and km and coll = trigger
rb.isKinematic = false;
coll.isTrigger = false;
//GunCarries momentum of player
rb.velocity = player.GetComponent<Rigidbody>().velocity;
//AddForce
rb.AddForce(fpsCam.forward * dropForwardForce, ForceMode.Impulse);
rb.AddForce(fpsCam.up * dropUpwardForce, ForceMode.Impulse);
//Enable Script
gunScript.enabled = false;
}
}
This is grapple hook script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GrappleGun : MonoBehaviour
{
private LineRenderer lr;
private Vector3 grapplePoint;
public LayerMask whatIsGrappable;
public Transform gunTip, camera, player;
private float maxDistance = 50f;
private SpringJoint joint;
void Awake()
{
lr = GetComponent<LineRenderer>();
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
StartGrapple();
}
if (Input.GetMouseButtonUp(0))
{
StopGrapple();
}
}
void LateUpdate()
{
DrawRope();
}
void StartGrapple()
{
RaycastHit hit;
if (Physics.Raycast(camera.position, camera.forward, out hit, maxDistance, whatIsGrappable))
{
grapplePoint = hit.point;
joint = player.gameObject.AddComponent<SpringJoint>();
joint.autoConfigureConnectedAnchor = false;
joint.connectedAnchor = grapplePoint;
float distanceFromPoint = Vector3.Distance(player.position, grapplePoint);
//the distance
joint.maxDistance = distanceFromPoint * 0.8f;
joint.minDistance = distanceFromPoint * 0.25f;
joint.spring = 5f;
joint.damper = 0;
joint.massScale = 1f;
lr.positionCount = 2;
}
}
void DrawRope()
{
//if not grappling
if (!joint) return;
lr.SetPosition(0, gunTip.position);
lr.SetPosition(1, grapplePoint);
}
void StopGrapple()
{
lr.positionCount = 0;
Destroy(joint);
}
public bool IsGrappling()
{
return joint != null;
}
public Vector3 GetGrapplePoint()
{
return grapplePoint;
}
}
I think a better way for your situation would be to create an empty game object where you want the grappling gun to be held when it's picked up, and the empty game object parented to the camera from the scene. Then from the script, you can write these lines of code.
To reference the empty game object:
public transform gunHoldPosition;
And you can attach that from the scene view in Unity.
Then to make the gun snap to the position when it's held:
private void PickUp()
{
equipped = true;
slotFull = true;
transform.localPosition = Vector3.zero;
transform.localScale = Vector3.one;
//Enable rb and km and coll = trigger
rb.isKinematic = true;
coll.isTrigger = true;
//Enable Script
gunScript.enabled = true;
}
Now In the Update function, you have to write a little more:
private void Update()
{
//equipped and e is pressed
Vector3 distanceToPlayer = player.position - transform.position;
if (!equipped && distanceToPlayer.magnitude <= pickUpRange && Input.GetKeyDown(KeyCode.E) && !slotFull) PickUp();
//Drop if equipped and q is pressed
if (equipped && Input.GetKeyDown(KeyCode.Q)) Drop();
if (equipeed){
/* If this script is on the gun itself, then you just have to do transform.position, but if it's on some other object then you have to reference the gun that's being picked with the variable of 'public gameObject gun;' up and say gun.transform.position*/
transform.position = gunHoldPosition.position;
}
}
I'm not exactly sure why you have to do this in the Update function, but once I made a pickup script and the same thing happened to me, so I had to put the transform.postition in the Update Function. Hopefully this works for you if it doesn't reply to me and I will try something else.
Also sorry that I am late to answer my question even though I fixed it really fast. I was making the object with the script, aka a child of the model without actually making the model a child of thing.

Npc animation following player unity 2d top down

Hey I am making a top down game in unity. The problem I ma having is making npc players change the way they are facing while following the player. So if the player turns left the npc follows them but doesn't turn to face the direction the npc is going. I can get the npc to look like its walking just not change the direction it is looking. This is a 2d top down game please any help will be nice. here is my npc code.
using UnityEngine;
using System.Collections;
public class SlimeController : MonoBehaviour
{
public Transform Character; // Target Object to follow
public float speed = 0.1F; // Enemy speed
public float maxDist = 10.0f;
public float attackdistance = 3;
public float farenough;
private Vector3 directionOfCharacter;
private bool challenged = false;// If the enemy is Challenged to follow by the player
public Transform StartMarker;
private Vector3 goback;
public Transform EndMarker;
public Rigidbody2D rb;
Animator anim;
float oldx;
bool left;
bool right;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
anim= GetComponent<Animator>();
oldx = transform.position.x;
}
void Update()
{
anim.SetBool("left", false);
anim.SetBool("right", false);
var distanceFromPlayer = Vector3.Distance(Character.position, transform.position);
if(oldx>transform.position.x)
{
left = false;
right = true;
}
if(oldx<transform.position.x)
{
left = true;
right = false;
}
if (oldx == transform.position.x)
{
left = false;
right = false;
}
if (challenged)
{
directionOfCharacter = Character.transform.position - transform.position;
directionOfCharacter = directionOfCharacter.normalized; // Get Direction to Move Towardsss
transform.Translate(directionOfCharacter * speed, Space.World);
enabled = true;
if (distanceFromPlayer < attackdistance)
{
attack();
}
if (distanceFromPlayer > attackdistance)
{
speed = 0.03f;
}
}
if (!challenged)
{
goback = StartMarker.transform.position - transform.position;
goback = goback.normalized;
transform.Translate(goback * speed, Space.World);
}
}
// Will be triggered as soon as player would touch the Enemy Object
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.name == ("Player"))
{
challenged = true;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.gameObject.name == ("Player"))
{
speed = 0.03f;
challenged = false;
}
}
void attack()
{
speed = 0;
transform.Translate(directionOfCharacter * speed, Space.World);
}
}
This is because you are just moving the object towards your target. But to have it look at your target you need to also rotate it in the direction of your target.
The Transform Component has a function called LookAt. You supply it with your Target and the Axis your object should rotate around. So in your case:
this.transform.LookAt(Character, Vector3.up);
See here for more info on LookAt.

How to prevent a player from moving through walls in Unity3d

I've got the following player controller:
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
[RequireComponent(typeof(NetworkIdentity))]
public class PlayerController : NetworkBehaviour {
public Vector3 size = new Vector3(1, 1, 1);
public float speed = 10;
public float rotateSpeed = 9;
private Transform _transform;
private Map _map;
private BoxCollider _collider;
private bool _active = false;
private Vector3 _lastPosition;
private bool _isGrounded = false;
void Start () {
_transform = transform;
Messenger.AddListener ("MAP_LOADED", OnMapLoaded);
_transform.localPosition = new Vector3 (-100, -100, -100);
gameObject.name = "Player " + gameObject.GetComponent<NetworkIdentity> ().netId.Value;
_collider = gameObject.GetComponent<BoxCollider> ();
_map = GameObject.Find ("Map").GetComponent<Map> ();
_collider.size = size;
}
void OnMapLoaded () {
if (isLocalPlayer) {
// Hook up the camera
PlayerCamera cam = Camera.main.GetComponent<PlayerCamera>();
cam.target = transform;
// Move the player to the it's spawn location
_transform.localPosition = _map.GetPlayerSpawn();
}
// Set the player as active
_active = true;
}
void Update () {
if (!isLocalPlayer || !_active) {
return;
}
_lastPosition = _transform.position;
float transAmount = speed * Time.deltaTime;
float rotateAmount = rotateSpeed * Time.deltaTime;
if (Input.GetKey ("up")) {
transform.Translate (0, 0, transAmount);
}
if (Input.GetKey ("down")) {
transform.Translate (0, 0, -transAmount);
}
if (Input.GetKey ("left")) {
transform.Rotate (0, -rotateAmount, 0);
}
if (Input.GetKey ("right")) {
transform.Rotate (0, rotateAmount, 0);
}
if (!_isGrounded) {
Vector3 down = _transform.TransformDirection(Vector3.down);
_transform.position += down * Time.deltaTime * _map.gravity;
}
}
void FixedUpdate () {
//
// Check what is below us
//
Vector3 down = _transform.TransformDirection(Vector3.down);
RaycastHit[] hits;
hits = Physics.RaycastAll(_transform.position, down, size.y + 0.001f);
_isGrounded = false;
foreach (RaycastHit hit in hits) {
if (hit.collider.gameObject.tag.ToUpper() == "GROUND") {
_isGrounded = true;
}
}
}
void OnTriggerEnter(Collider collider) {
Debug.Log ("Triggered by " + collider.gameObject.tag.ToUpper ());
if (collider.gameObject.tag.ToUpper () == "GROUND") {
transform.position = _lastPosition;
}
}
}
In Update I'm taking the user's input and moving the transform around. In FixedUpdate I'm checking to see if the player is on the ground and setting a flag appropriately. And finally in OnTriggerEnter I'm checking to see if I'm trying to go through anything.
If in OnTriggerEnter I hit something I try to set the player's position back to a good one, but that's not happening. My guess is because _lastPosition isn't what I'm expecting it to be.
Is there a better way to do this?
Use rigidbody.Move(position) instead of transform.Translate(position).
Note: Using transform.translate causing performance issues and you must handle collision detection manually.

Categories

Resources