so i wrote a sript that when my Player touches my enemy. my Player respawn should know that my camera is following my player. But when I respawn, she moves behind my background
how to do?
My scipt
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Respawn : MonoBehaviour
{
[SerializeField] Transform spawnPoint;
void OnCollisionEnter2D(Collision2D col)
{
if (col.transform.CompareTag("Player"))
col.transform.position = spawnPoint.position;
}
}
//Thanks
There are two things you could do:
Use z axis to place object (player) in front.
Use sorting layers and sorting group component.
Related
Hi!
After the discussion with Ruzihm in the comments. I've now created a simple version of my game to better ask the question I'm having.
The question now is, since I'm not able to manually create a connection to the testObject field in the inspector. How do I now tell Unity to use my instantiated objects while the game is running?
And is this a good solution for a RTS game that may have 100s of Units active at a time? The end goal here is to apply this force to a radius around the cursor. Which I was thinking of using Physics.OverlapSphere
Here's the minimal scenario of what I have:
New Unity scene
Attached the InputManager to the main camera.
Created a capsule and a plane.
Added ApplyForce to the Capsule
Created a prefab from the capsule and deleted it from the scene.
In the InputManager I added the ability to press space to Instantiate a capsule with the ApplyForce script attached..
Drag the capsule prefab to the InputManager "objectToGenerate"
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GL.RTS.Mites
{
public class InputManager : MonoBehaviour
{
public GameObject testObject;
public ApplyForce onSpawnTest;
public GameObject objectToGenerate;
void Start()
{
onSpawnTest = testObject.GetComponent<ApplyForce>();
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
Instantiate(objectToGenerate);
}
if (Input.GetMouseButton(0))
{
onSpawnTest.PushForward();
}
}
}
}
The ApplyForce script that I attach to the Capsule:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GL.RTS.Mites
{
public class ApplyForce : MonoBehaviour
{
public float moveSpeed;
Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
Debug.Log("A Mite has spawned!");
}
public void PushForward()
{
rb.AddRelativeForce(Vector3.up * moveSpeed * Time.deltaTime);
Debug.Log("A force of: " + moveSpeed + " is being added.");
}
}
}
Well, you are creating your new instances of your object, but your input manager immediately forgets about them (note that you do nothing with the return value). The InputManager only knows about the ApplyForce that was created in its Start (and then interacts with it depending on mouse input) and your ApplyForce script knows nothing about any InputManager. So, it should come as no surprise that only the first instance reacts to the mouse input.
So, something has to be done to your InputManager and/or your ApplyForce. Your InputManager could remember the instances it creates (which isn't enough, because what if for example, a map trigger creates new player controllable units) or it could go looking for units each time.
Your ApplyForce could register with the InputManager when they are created, but then you would need to loop through the units and find out which ones are under the mouse, anyway.
Since you only want to select ones based on what is near or under your cursor and only when input occurs and not like every frame, I would go with the simplest approach, just letting your InputManager find the units when it needs them. Something like below, explanation in comments:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace GL.RTS.Mites
{
public class InputManager : MonoBehaviour
{
public GameObject testObject;
public ApplyForce onSpawnTest;
public GameObject objectToGenerate;
private Camera mainCam;
// which layers to consider for cursor detection
[SerializeField] LayerMask cursorLayerMask;
// how big for cursor detection
[SerializeField] float cursorRadius;
void Awake()
{
// cache main camera
mainCam = Camera.main;
}
void Update()
{
if(Input.GetKeyDown(KeyCode.Space))
{
Instantiate(objectToGenerate);
}
if (Input.GetMouseButton(0))
{
Collider[] colls = FindCollidersUnderCursor();
// check each collider for an applyforce and use it if present
foreach( Collider coll in colls)
{
ApplyForce af = coll.GetComponent<ApplyForce>();
if (af != null)
{
af.PushForward();
}
}
}
}
Collider[] FindCollidersUnderCursor()
{
// find ray represented by cursor position on screen
// and find where it intersects with ground
// This technique is great for if your camera can change
// angle or distance from the playing field.
// It uses mathematical rays and plane, no physics
// calculations needed for this step. Very performant.
Ray cursorRay = mainCam.ScreenPointToRay(Input.mousePosition);
Plane groundPlane = new Plane(Vector3.up, Vector3.zero);
if (groundPlane.Raycast(cursorRay, out float cursorDist))
{
Vector3 worldPos = cursorRay.GetPoint(cursorDist);
// Check for triggers inside sphere that match layer mask
return Physics.OverlapSphere(worldPos, cursorRadius,
cursorLayerMask.value, QueryTriggerInteraction.Collide);
}
// if doesn't intersect with ground, return nothing
return new Collider[0];
}
}
}
Of course, this will require that every unit you're interested in manipulating has a trigger collider.
Im trying to make a system in which my UI will display the nearest enemys health and sprite. I have already got the panels and UI working to display the Player health but im unsure as to how to display whichever enemy has came close or within range of the player.
** The game is running around but coming within range of an enemy triggers combat**
The below code can display a characters health if I place the script on the player/enemy. Im grabbing two variables from Bolt also.
I can display a single enemy no problem in this way. But if i put 50 enemies in one scene it means I have to manually load the panels/UI for each enemy.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Bolt;
using Ludiq;
using UnityEngine.UI;
public class HealthAndCombat : MonoBehaviour
{
public GameObject player;
public Slider healthBarSlider;
public float health;
private bool inCombat;
private GameObject nearestEnemy;
public GameObject healthBarCanvas;
public GameObject bestFighterUI;
private void Start()
{
healthBarSlider.value = health;
bestFighterUI.SetActive(false);
}
void Update()
{
health = (float)Variables.Object(player).Get("Health");
inCombat = (bool)Variables.Object(player).Get("combat");
nearestEnemy = (GameObject)Variables.Object(player).Get("nearestEnemy");
if (inCombat)
{
healthBarCanvas.SetActive(true);
bestFighterUI.SetActive(true);
healthBarSlider.value = health;
}
else {
healthBarCanvas.SetActive(false);
bestFighterUI.SetActive(false);
}
}
Im thinking -
-Load the scene.
-Find all objects called enemy and register their health in a list.
-Work out distance from player to each enemy.
-If player in combat, display nearest enemy to player.
I just dont know should I have an overall scene manager for code or have scripts for detection on each player.
I am trying to build a flappy bird like game and I am trying to spawn enemy birds and gold coins so I have written the C# code and the made the prefabs, but when I run the bird and the coins are not respawning.
This is the respawn code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnPlayer : MonoBehaviour
{
public GameObject GameObjectToSpawn;
private GameObject Clone;
public float timeToSpawn = 4f;
public float FirstSpawn = 10f;
// Update is called once per frame
void Update()
{
FirstSpawn -= Time.deltaTime;
if (FirstSpawn <= 0f)
{
Clone = Instantiate(GameObjectToSpawn, gameObject.transform.localPosition, Quaternion.identity) as GameObject;
FirstSpawn = timeToSpawn;
}
}
}
screenshot of unity:
This where i am respawning the first enemy bird:
From your second screenshot it seems to be spawned but way off the screen! You can still see the tiny little island in the bottom left corner.
You thought seems to be that you have to spawn it in the Canvas pixel space using the spawn point's localPosition. But this is not the case since Instantiate places it into the scene root (without any parent) with absolute world-space position into the scene.
You should rather actually place the spawn point to the absolute world position where the spawn should happen and rather use
Clone = Instantiate(GameObjectToSpawn, transform.position, Quaternion.identity);
Btw no need for the as GameObject since Instantiate already returns the type of the given prefab.
Screenshot of the bullets when firing :
The bullets are stay still and they are standing.
This screenshot show the Fire Point inspector position rotation scaling :
And a screenshot of the bullet prefab settings :
Last screenshot show the Shooting gameobject inspector settings :
And the script Shooting :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shooting : MonoBehaviour
{
[SerializeField]
private Transform[] firePoints;
[SerializeField]
private Rigidbody projectilePrefab;
[SerializeField]
private float launchForce = 700f;
public void Update()
{
if (Input.GetButtonDown("Fire1"))
{
LaunchProjectile();
}
}
private void LaunchProjectile()
{
foreach (var firePoint in firePoints)
{
var projectileInstance = Instantiate(
projectilePrefab,
firePoint.position,
firePoint.rotation);
projectileInstance.AddForce(firePoint.forward * launchForce);
}
}
}
And how can I make that it will not leave a trail of bullets behind ?
For the rotation you want to set the projectile to the same rotation as the weapon.
transform.rotation = Quaternion.Euler(gunAngle)
the projectile should be another gameObject instead of rigidBody.
you'll also need a destruction script on them or they'll never disappear and you will have a million projectiles in play lagging the game. destroy gameObject by collision and time.
Regarding the trail of bullets, you should consider adding a cooldown to the LaunchProjectile method. Right now every time update is called it calls LaunchProjectile if the fire button is down, even if it called LaunchProjectile the update before (at 60 ups(?) you'd have to be pretty fast off of the fire button to only shoot one projectile).
camera transform
I am trying to move my camera based on the players' movements on Y axis in Unity.
However, it does not work...
What did I do wrong? I have attached image of my script (C#) here.
and, Yes, I did attach this script with Main Camera.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraController : MonoBehaviour {
GameObject player;
// Use this for initialization
void Start () {
this.player = GameObject.Find("cat");
}
// Update is called once per frame
void Update () {
Vector3 playerPos = this.player.transform.position;
transform.position = new Vector3(
transform.position.x, playerPos.y, transform.position.z);
}
}
Make the player GameObject public and just drag and drop your player in the inspector in unity see if that works? Are you getting any exceptions? Also add Debug.Log (player.transform.position.ToString ()) to see if it is showing the right values. Are you sure you player object name is cat and not Cat, it is case sensitive. Check on those things and let me know if you figured it out!