Getting closest possible destination - Unity3d - c#

I'm trying to understand how to get the closest to a destination with Unity's navigation system when a Nav Mesh Obstacle is in the way.
I have this example with a Capsule obstacle (with Carve on) and a capsule agent managed with a script. It seems to work okish, but when I "click" on the obstacle to set the destination of the agent (to a point inside the carved area), the agent moves to another location around the obstacle.
How can I make the agent go to the closest point around the obstacle or to the closest point to the selected destination (that is inside the area of the obstacle)?
Script to move the agent
using UnityEngine;
using UnityEngine.AI;
public class CapsuleMovement : MonoBehaviour {
NavMeshAgent agent;
public NavMeshPathStatus partial;
void Start() {
agent = GetComponent<NavMeshAgent>();
}
void Update() {
if (Input.GetMouseButtonDown(0)) {
RaycastHit hit;
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100)) {
agent.destination = hit.point;
}
}
}
}

Take the center of the clicked objects position and move it slightly towards the moving unit/player, then use that position as your coordinate instead of the direct mouse click.
If that doesn't work.
This is not a guaranteed answer as that is hard to give in a situation such as this, but I hope this brings you further.
I suspect that it may be the coordinate you click, which something is not working out as it should with. Try spawn a "ClickObject" which can just be a coloured sphere, at the position of the mouse click. That way you can confirm where the click actually is happening.
Here is furthermore 2 methods that may come in handy when working with NavMeshes and positioning.
You could try use SamplePosition.
https://docs.unity3d.com/540/Documentation/ScriptReference/NavMesh.SamplePosition.html
Finds the closest point on NavMesh within specified range.
Perhaps also FindClosestEdge
https://docs.unity3d.com/530/Documentation/ScriptReference/NavMesh.FindClosestEdge.html
Locate the closest NavMesh edge from a point on the NavMesh.

Related

Unity clamped UI Image is shaking

I am using the followng script to clamp the UI Image to the player in 2D game, but when the player is moving, the image is shaking a little. What am I doing wrong?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HealthBarClamp : MonoBehaviour
{
public Transform targetToFollow;
Transform thisTransform;
void Start()
{
thisTransform = transform;
}
void Update()
{
thisTransform.position = new Vector3(targetToFollow.position.x,
targetToFollow.position.y + 1.5f, thisTransform.position.z);
}
}
You can try to make the health bar children of your target in the gameObject hierarchy, so that it moves along with it with no need of updating its position in a script. You can then enable/disable the health bar upon your needs if you need it to be seen or not
If you're moving the target object around using physics or in FixedUpdate, then you'll need to move the camera around in FixedUpdate as well. Update happens every frame, fast or slow, whereas FixedUpdate is simulated to happen at consistent intervals to help keep physics calculations from going nuts. If you move the camera in Update and the target in FixedUpdate, then you'll end up with tiny differences that look like shaking.
(Or you can follow the advice given in the comments. It works perfectly fine to make a UI element a child of the moving object, although I personally prefer to do it the way you had it originally because it makes things like "smooth" camera movement easier.)

Camera.main.ScreenToWorldPoint(Input.mousePosition) always returns camera position, doesnt matter where i click

I am trying to create a script that converts mouseclick position into position in GridLayout. I trying to use Camera.main.ScreenToWorldPoint(), but its returning coordinates of camera, not of the point clicked, doesnt metter if i use static camera or camera fixed on player. I attached this script to CharacterRobotBoy prefab from standard unity assets.
using UnityEngine;
public class Position : MonoBehaviour
{
void Update()
{
if (Input.GetMouseButtonUp(0))
{
Vector3 pz = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Debug.Log("camera:"+pz);
pz.z = 0;
GridLayout gridLayout = transform.parent.GetComponentInParent<GridLayout>();
Vector3Int cellPosition = gridLayout.WorldToCell(pz);
Debug.Log("cell position:"+cellPosition);
}
}
}
Can my code be fixed for the task, or is there a different solution for the problem. Thanks for your help.
PS: I am new to unity.
Suppose you have a flat plane and a camera looking at it from above.
Think of the screen as the lens of the camera, and the cursor as a small ant walking over it. If I remember correctly, ScreenToWorldPoint returns the location of the ant in world-space, which is somewhere in the sky. By setting z := 0, you get a point directly below the camera, regardless of where the cursor is.
What you should do instead is cast a ray from the center of the camera-view through the ant, and collide it with the plane. The collision point is what you are looking for.
It can be done via the ScreenPointToRay method.
You should check out Brackeys RPG tutorial, he's done something similar.
Hope it helps :)

Unity3D OnPointerClick is based on cam position?

Ok so I'm completely lost on how to approach this problem. I have a implementation of IPointerClickHandler that goes something like this :
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log(gameObject.name);
//Othe rstuff
}
So at least every object with this attached to it should print out its name to the console. Now I have 2 screenshot to further Explain the Problem.
The two tiles with the lilipop and the briefcase do not fire OnPointerClick when the camera is in this position.
Move the cam a bit to the right and the event is firec correcrtly.
What have I checked/tried:
Nothing is blocking the object
The camera has a 2D Physics Ray caster attached to it. Its layers are correct.
The tiles have BoxCollider2Ds.
Edit: Did a simple raycast test; THis is the code attached to the camera. This hits from any position as long as even part of the collider is vissible on screen. While if even a part of the collider is near the edge of the viewport or outside of it. OnPointerClick does not work. How do I solve this?
public class RayCasterTest : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Vector3 pos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
RaycastHit2D hit = Physics2D.Raycast(pos, Vector2.up, 0.0f);
if (hit.collider != null)
Debug.Log(hit.collider.gameObject.name);
}
}
Ok so how do I explain this. I have a big 2dBoxcollider behind everything. I use it as camera bounds. Now for some reason from time to time the EventSystem would hit it and not the correct collider that is definitely on top if it. Setting this collider to a layer excluded from the Physics3d raycaster seems to have fixed the problem.

Create ability radius Unity C#

I'm developing a unity game's ability system in which some of the spells have specific range, I'm not quite sure how to do that but here's what i camed up with.
I will need some sort of sphere which will be invisible and the center of it will be my character.
The radius of the sphere will be equal to the range of the spell selected.
My spells are being cast over the mouse position which means i will be able to check if the sphere is colliding with the mouse.
Overall this idea with the sphere seems good to me because later on i will be able to add color to it so the user can also see the phsycal range of the spell if he want's to. But i see a few problems :
The mouse is moving only in 2 dimension x and y however for a 2D object collission to be detected the method requires another 2D colider, well the sphere is 3D.
private void OnTriggerEnter2D(Collider2D other)
{
}
I'm not sure how to make let's say 500 pixels range to be still relative to my screen and therefore this to be the actual radius of the sphere because my characters dont seem to move huge distance when i'm looking at the x axis, they move just a tiny bit and making a sphere with radius of 500 on the x axis will be complete disaster.
As i said I'm not sure how to make this, I'm new to unity and i'm not sure how to implement my idea, so any help or tips are welcome.
You need to project your mouse in 3D to do the collision check. (You can imagine your mouse shooting a line right in front of it) You can do that using raycast:
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if ( Physics.Raycast (ray,out hit,100.0f))
{
if(hit.collider == yourSphereCollider)
{
// the mouse was pointing at the sphere
}
}
Note that if there is another collider between the sphere and the mouse, it will be detected instead.
You can also use the same technique to determine where on the ground your effect should be displayed

Block collision

another question, my player is a square, and when he hits this pressure plate for example, this happen: https://i.gyazo.com/7866da3f8371aee6c319fd447f1bee95.gif
My code in the pressure plate object is this:
Animator pressionar;
public Transform playerCheck;
public LayerMask playerLayer;
public bool pressured = false;
void Start () {
pressionar = GetComponent<Animator>();
}
void Update () {
pressionar.SetBool("Pressionado", pressured);
pressured = Physics2D.OverlapCircle(playerCheck.position, 0.15f, playerLayer);
}
I tried changing to circle collision but didn't change nothing, thanks.
There are a few possible ways to solve this that I can think of.
First: Try locking the rotation of the square's z axis in the RigidBody2D. It's within the Constraints section.
Second: Try creating a ramp for the square to slide onto the button. You could do this using a Polygon Collider. See link for details.
http://docs.unity3d.com/Manual/class-PolygonCollider2D.html
Third: Use a script to activate an OnCollisionEnter function that would place the square onto the button, or to push down the button, which would allow the cube to slide on. See link for details.
http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnCollisionEnter2D.html
Hopefully these resources can be of some help to you. You can mix and match to try and find a method that gives you the best result.

Categories

Resources