How to create an object to follow my Player - unity3d

I'm looking for a way to do something like this:
Gradius
In this game, orbs are following the player. How to do this in Unity where my orbs are following my Player.
Thanks!

A simple solution that i have thought is, lets say i have a player and it is holding it's previous position at start and whenever it moves lets say 5 units then we say to the object that will follow it to follow it's previous position and then we update player's previous position to it's current position and we follow same steps.
I have created a simple test scene and followed these steps :
I have created 2 game objects called Player and FollowPlayer
I have wrote the script below and attached it to the Player
public static event Action<Vector3> FollowMe;
[SerializeField] private float _followDistance;
private Vector3 _previousPosition;
private void Start()
{
_previousPosition = transform.position;
}
private void Update()
{
if(Vector3.Distance(transform.position,_previousPosition) > _followDistance)
{
if(FollowMe != null)
{
FollowMe.Invoke(_previousPosition);
}
_previousPosition = transform.position;
}
}
Then for the FollowPlayer object i have wrote the script below and attached to it
private void Start()
{
Player.FollowMe += OnFollowMe;
}
private void OnDestroy()
{
Player.FollowMe -= OnFollowMe;
}
private void OnFollowMe(Vector3 position)
{
transform.position = position;
}
Again, this is a simple follow script same logic in the Gladius game and i am sure you can use this idea and make it more generic and usable.

Related

how to get my clawhand to grab my objectholder?

[![ hey guys so i need help please! i need my claw hand to be able to grab my object holder(orange thingy next to the red ball. my objectholder has a spring joint already so I want my clawhand to be able to grab it and pull it with the ball. When my hand opens then it shoots. But when I try to grab it, my hand goes right through.
My claw hand has rigidbody,box collider,configuration joint and is animation by this code
public class open2close : MonoBehaviour
{
public float speed;
private Animation anim;
Rigidbody rb;
void Start()
{
anim = gameObject.GetComponent<Animation>();
rb = GetComponent<Rigidbody>();
}
void Update()
{
//********************Open pincher ********************
if (Input.GetKey(KeyCode.X))
{
anim.Play("clawopen");
}
//*******************Close pincher ********************
if (Input.GetKey(KeyCode.Y))
{
anim.Play("clawclose");
}
}
}
as for my object holder it has box collider,spring joint, rigidbody, and rotation constraint. Can someone guide me or help me in what i can do thank you.
It is probably best to not have a collider on the claw hand. This is because you are mixing rigidbodies with animation, which can get messy. I would reccomend keeping everything, excpt for the box collider on the claw hand. Set it to a trigger. You can put booleans in the if statements to open and close the claw. This way, you can set the position of the objectholder to be at the claw (if they are touching).
Change your script to something like
public class open2close : MonoBehaviour
{
public float speed;
private Animation anim;
[SerializeField] bool isClosed;
Rigidbody rb;
void Start()
{
anim = gameObject.GetComponent<Animation>();
rb = GetComponent<Rigidbody>();
}
void Update()
{
if (Input.GetKey(KeyCode.X))
{
anim.Play("clawopen");
isClosed = false;
}
if (Input.GetKey(KeyCode.Y))
{
anim.Play("clawclose");
isClosed = true;
}
}
void OnTriggerStay(Collider obj)
{
Rigidbody colRb = obj.attachedRigidbody;
if (colRb != null && isClosed)
{
colRb.position = transform.position;
}
}
}
Let me know if this works and be specific! thanks :)

How to show a trigger only when pointing to it directly?

I created a transparent cube trigger and I placed it in front of closed doors, so whenever the player walks near the door a message appears saying "this door is locked".
However, I want the message to be gone whenever the player is Not pointing to the door. currently, it shows even when I turn around, the player needs to walk away from the door to make the message disappear.
Here is my code:
public class DoorsTrigger : MonoBehaviour
{
public GameObject partNameText;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
partNameText.SetActive(true);
}
}
private void OnTriggerExit(Collider other)
{
if (other.CompareTag("Player"))
{
partNameText.SetActive(false);
}
}
}
How can I modify it to achieve my goal?
Here is a simple example using Vector3.Angle() to get the direction the player is facing relative to that trigger.
public class DoorsTrigger : MonoBehaviour
{
public GameObject partNameText;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
//Assuming 'other' is the top level gameobject of the player,
// or a child of the player and facing the same direction
Vector3 dir = (this.transform.position - other.gameObject.transform.position);
//Angle will be how far to the left OR right you can look before it doesn't register
float angle = 40f;
if (Vector3.Angle(other.gameObject.transform.forward, dir) < angle) {
partNameText.SetActive(true);
}
}
}
private void OnTriggerExit(Collider other)
{
//Make sure the text is actually showing before trying to disable it again
if (other.CompareTag("Player") && partNameText.activeSelf)
{
partNameText.SetActive(false);
}
}
}
Alternatively, you can keep your trigger mostly as is, and do a ray cast from the player to see if they are looking at the door.
//Put this snippet in a function and call it inside the player's Update() loop
RaycastHit hit;
Ray ray = new Ray(this.transform.position, this.transform.forward);
if(Physics.Raycast(ray, out hit))
{
//Tag the gameObject the trigger is on with "Door"
if(hit.collider.isTrigger && hit.collider.CompareTag("Door"))
{
//Here is where you would call a function on the door trigger to activate the text.
// Or better would be to just have that code be on the player.
// That way you can avoid unnecessary calls to another gameObject just for a UI element!
}
}

Trying to make sliding puzzel game in unity. But the puzzel piece don't move

I am trying to make simple sliding puzzel game in unity. I used https://youtu.be/rJFprTG3wE0 this video as tutorial. In the video block move if clicked but mine doesn't.
using UnityEngine;
public class gamebasic : MonoBehaviour
{
[SerializeField] public Transform empty =null;
private Camera _camera;
// Start is called before the first frame update
void Start()
{
_camera = Camera.main;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(ray.origin, ray.direction);
if (hit)
{
if (Vector2.Distance(a: empty.position, b: hit.transform.position) < 1)
{
Vector2 lastemptyposition = empty.position;
empty.position = hit.transform.position;
hit.transform.position = lastemptyposition;
}
}
}
}
}
Here is my code and I am using visual studio 2017 version 15.9.39 and unity 2020.3.11f1.
At the end of the video he makes a comment about changing the value of the distance, if your reference to the empty transform is correct that might be the reason.
You can make this a public variable and test different values, like this:
[SerializeField] private float maxDistanceToEmpty = 2f;
and then you change that line to
if (Vector2.Distance(a: empty.position, b: hit.transform.position) < maxDistanceToEmpty )

Why more balls are instantiating?

I'm making a game in unity where the user drags to shoot a ball at some objects at a distance. So far I have this DragAndShoot script:
//using System.Collections;
//using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(Collider))]
public class DragAndShoot : MonoBehaviour
{
public Transform prefab;
private Vector3 mousePressDownPos;
private Vector3 mouseReleasePos;
private Rigidbody rb;
private bool isShoot;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void OnMouseDown()
{
mousePressDownPos = Input.mousePosition;
}
private void OnMouseUp()
{
mouseReleasePos = Input.mousePosition;
Shoot(mouseReleasePos-mousePressDownPos);
}
private float forceMultiplier = 3;
void Shoot(Vector3 Force)
{
if(isShoot)
return;
rb.AddForce(new Vector3(Force.y,Force.x,Force.z) * forceMultiplier);
isShoot = true;
createBall();
}
void createBall(){
Instantiate(prefab, GameObject.Find("SpawnPoint").transform.position, Quaternion.identity);
}
}
As you can see, I made the function createBall() in order to respawn a ball prefab at the position of the game object SpawnPoint. When I run the game, the first ball shoots fine. And another ball respawns.
Issue: when I shoot the second ball and it moves, one more ball seems to have appeared at the second ball somehow, and it moves as well. Not sure why this is happening and how to fix it - can someone pls help? Thanks.
The problem is that you need to Destroy() the game object you threw first. Since you are just bringing the objects back when click down again, here is what you should do:
Make it so that it destroys the old object. Because you just keep instantiating the object, then when you throw it again it throws the old one too. If you understand what I mean, then hopefully, you can turn this into what you want. (It wasn’t exactly clear what your game was; this is what I interpreted)

Physics OverlapSphere does not detect Collision

I wanted to create an collider on my players sword, that if he attacks that he would detect and via an animation event turn off/on an gameobject called (Damage Point) who was an script attached that would subtract the enemys health.
But somewhere it does not detect correctly. I tried to add the OnDrawGizmos function to see my sphere collider but even after making it bigger it does not detect.
The most strange thing about my issue is that im using the same code for my monster chest and my fantasy player, but for the chest it works but for the player it does not.
I created a class called PlayerDamage that is attached on an empty gameobject to the tip of my sword.
{
public class PlayerDamage : MonoBehaviour
public int damageAmount = 2;
public LayerMask enemyLayer;
void Update()
{
Collider[] hits = Physics.OverlapSphere(transform.position, 1.7f, enemyLayer);
if (hits.Length > 0)
{
if (hits[0].gameObject.tag == MyTags.ENEMY_TAG)
{
print("COLLIDED WITH ENEMY");
}
}
}
private void OnDrawGizmos()
{
Gizmos.DrawWireSphere(transform.position, 1.7f);
}
In another script called PlayerScript that is attached directly to the player I have a function called Attack:
void Attack()
{
if (Input.GetKeyDown(KeyCode.K))
{
if (!anim.GetCurrentAnimatorStateInfo(0).IsName(MyTags.ATTACK_ANIMATION) || !anim.GetCurrentAnimatorStateInfo(0).IsName(MyTags.RUN_ATTACK_ANIMATION))
{
anim.SetTrigger(MyTags.ATTACK_TRIGGER);
}
}
}
Also in the PlayerScript class there are two functions called ActivateDamagePoint and DeactivateDamagePoint, these are assigned to animation events for the attack animations.
void ActivateDamagePoint()
{
damagePoint.SetActive(true);
}
void DeactivateDamagePoint()
{
damagePoint.SetActive(false);
}
I double checked that everything is on his layer and that the tags are okay, but that did not solve my problem.
Like I said before for the chest I use the same code and it works, but unfortunately it does not work with my player. I also have the Activate and Deactivate DamagePoint functions in there and these are also called by the animation event for my chest attack animation.
Okay after 1hour of debugging I finnaly found the solution:
It was in the MyTags class (a helper class for all the string variables), the error was:
public static string ENEMY_TAG = "Enemey";
instead of:
public static string ENEMY_TAG = "Enemy";