I have two scripts like this:
void Update()
{
if (Input.GetMouseButton(0))
{
if (GameObject.FindGameObjectWithTag("Object").transform.position.x > -1.9)
{
GameObject.FindGameObjectWithTag("Object").transform.Translate(Vector2.left * szybkosc);
}
}
}
And second script is similiar, only there is "Vector2.right" difference. If I have one script, it works perfectly, but when I add second script, they doesn't work. I add these scripts to two different gameobjects.
And second script is similiar, only there is "Vector2.right"
difference
That's the problem right there.
You are moving the object left with ("Object").transform.Translate(Vector2.left * szybkosc);
then you have another script that is moving it right with ("Object").transform.Translate(Vector2.right * szybkosc);.
What do you expect to happen? I think that the "Object" GameObject should remain still or even create a weird behavior. You can't be moving one Object to two opposite directions at the-same time.
Maybe the second script is supposed to be moving another GameObject GameObject.FindGameObjectWithTag("AnotherObject") instead of the first GameObject the first script is already moving....
Not related to your problem but you should call GameObject.FindGameObjectWithTag once in the Start function.
GameObject objToMove;
void Start()
{
objToMove = GameObject.FindGameObjectWithTag("Object");
}
void Update()
{
if (Input.GetMouseButton(0))
{
if (objToMove.transform.position.x > -1.9)
{
objToMove.transform.Translate(Vector2.left * szybkosc);
}
}
}
EDIT:
I'm making control system. I have two arrows - left arrow and right
arrow. When I touch and hold left arrow, object moves left, when I
touch and hold right arrow, object moves right.
It's good to mention what you are doing in your question. This is what EventSystems is used for. OnPointerClick, OnDrag and OnEndDrag are used to make such things. You can find more about this here.
In fact, you need a Visual Joystick. Use Unity's CrossPlatformInputManager from the Asset store and that should do it. It will save you so much time of having to make your own with OnPointerClick and OnDrag .
The value from CrossPlatformInputManager.GetAxisRaw("Horizontal") can then be used to move your Object left or right.
Related
I am new to using unity and am having a real problem getting trigger collisions to register.
public void OnTriggerEnter2D(Collider2D other)
{
print("collide");
if (other.CompareTag("Fish"))
{
print("Caught");
}
}
I have 2D polygon colliders and a rigid body on both items. I have also got 1 set a trigger(have tried having both as trigger). However one UI item is a sprite and the other is an image.
Both items are also tagged with "fish"
Would really appreciate any help.
Thanks
There are four things I can think of which need to happen so that OnTriggerEnter gets called:
The two objects' colliders need to actually be overlapping. Just because their rendered pixels are overlapping, doesn't mean their colliders are overlapping. This can be checked in the editor. Their colliders are indicated with a green outline in the Scene tab. If you don't see anything, make sure the button labeled Gizmos is turned on.
The two objects need to be in physics layers which are set to collide with each other. You can check this in Edit > Settings > Physics2D > Layer Collision Matrix.
Both objects need to have Rigidbody2D components attached. Make sure these aren't Rigidbody components, as those are for 3D physics.
The object which contains the OnTriggerEnter2D event needs to have isTrigger = true.
I've tried several things to do.
First I've checked recommendations from another post.
In nutshell:
Checked if I have rigid body at least for one of objects
Checked layers
Checked tags
Played with "is trigger".
Finally, the solution was to add script to object via create and add component button and not to drop written script to it. Have no idea, but for me that was the solution. Even it was same script.
Both a Sprite and an Image can collide with another Image. What might be wrong is that your sprite may look like touching the image however in the scene the canvas might be far away, so camera may deceive you. Here is the sample code for my tests:
Script that moves the Sprite:
private Rigidbody2D _rigidbody;
private void Awake() => _rigidbody = GetComponent<Rigidbody2D>();
private void FixedUpdate()
{
if (Input.GetKey(KeyCode.A))
{
var movement = -transform.right * Time.fixedDeltaTime * 250;
_rigidbody.MovePosition(transform.position + movement);
}
if (Input.GetKey(KeyCode.D))
{
var movement = transform.right * Time.fixedDeltaTime * 250;
_rigidbody.MovePosition(transform.position + movement);
}
}
Trigger script on image:
private void OnTriggerEnter2D(Collider2D other)
{
Debug.Log(other.name);
}
Nothing helps for me, but in my case I didn't know there was a place in code that breaks collision layers (that is do not change the collision matrix settings visually):
Physics2D.IgnoreLayerCollision(...
Check that too and make sure it is not called.
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.
I am trying to create a Minesweeper + clicker/idle game for practice. For now, I can't get the clicking to work properly. I spawned in all objects through code meaning they are all the same prefabs but at different locations. When I click them the code activates for all of them and all of the tiles change to being open. I am not sure if I'm using the wrong click function here, as I know there is also an OnMouseDown() function instead of Input.GetMouseButtonDown(0) but the only one where the code activates is in the second one.
public class TileClick : MonoBehaviour {
public GameObject openTile;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButtonDown(0)) {
Instantiate(openTile, transform.position, Quaternion.identity);
Object.Destroy(this.gameObject);
}
}
}
That's my clicking detection. While it does detect clicks, as I said before, it detects them for ALL tiles and activates them all. I only want it to activate on one of them. I've seen RayCasting stuff but I really need more explanation on how that thing works (if that's the solution).
If the TileClick script component is attached to your prefab, then for every tile you instantiate, you have a corresponding TileClick component attached.
When you click, the input is detected by all of these blocks simultaneously, and each of them calls Instantiate but the transform.position is the one corresponding to the tile that makes the call. This is why it seems like all the tiles open up simultaneously, because you are, in fact, instantiating an "open" tile on each of them every time you click.
You should keep all your user input code in a separate MonoBehaviour, and attach that to a single empty GameObject in your scene. For detecting the hit, you should attach a 2DCollider component to your tile prefab (you can decide the type according to the shape of your tiles), and then just use a simple RayCast in your user input code to instantiate an "open" tile at the position where the hit occurs:
void Update () {
if (Input.GetMouseButtonDown(0)) {
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition),
Vector2.zero);
if(hit.collider != null)
{
Instantiate(openTile,
hit.collider.gameObject.transform.position,
Quaternion.identity);
}
}
I highly recommend understanding how RayCast works since it is a very useful tool. Here's a good place to start: https://docs.unity3d.com/ScriptReference/Physics2D.Raycast.html
What I'm trying to do is when it hits a triggered collider I want it to minus an int, but what unity does is minus it with 3 instead, and I have it attached to the player itself
lifecontroller lves;
public GameObject gm;
CoinScript coins;
// Use this for initialization
void Start () {
gm = GameObject.FindGameObjectWithTag("GM");
coins = gm.GetComponent<CoinScript>();
lves = gm.GetComponent<lifecontroller>();
}
void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Evil")
{
lves.lives -= 1;
Debug.Log("U hit it");
}
}
// Update is called once per frame
void Update () {
if(lves.lives == 0)
{
Debug.Log("u died");
}
}
Judging from the screenshot, your script is attached to the Player GameObject multiple times. Select your Player GameObject, and remove the duplicate Script.
Make sure there is only one script attached to it. It is probably attached there 3 times.
This problem can also happen if you are instantiating multiple Player GameObjects during run-time as this will duplicate your script too.
EDIT:
With the updated Image in your comment, the problem is that you have 3 Colliders on your Player. It is true that only one of them is made IsTrigger but this is a problem if the GameObject with the Evil tag is marked as IsTrigger too.
You have 2 options to fix this:
1.Select the GameObjects with the Evil tag and make sure that no Collider attached to it is marked as IsTrigger. Unceheck all IsTrigger properties on the Collider of all Evil tagged GameObjects only. This should fix your problem.
2.Only have one Collider on Player GameObject. Remove the other 2. This again should fix your problem.
The trigger is definitly happening 3 times, your screenshot shows that (there is a 3 on the right since duplicate logs get collapsed).
This might occur because of the collider shape I think (circle). Try using a bool that us set on trigger enter and clear on trigger exit (or even Update should be ok for clearing).
This is what I suggested to debug your problem:
void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Evil")
{
lves.lives -= 1;
Debug.Log("U hit it", other.gameObject);
}
}
And by looking at your screenshot you are getting 3 log messages.
Always use don't collapse in console window to see whats happening
I'm currently working on a script that can pick up an item, and drop it with the click of the left mouse button. I'm also planning on addint rotating of an item and some icons to display whenever i do one of those actions.
I'm currently very new to this, so i might be trowing myself out in the depths. But i would like to try.
Here's my code:
public class PickUp : MonoBehaviour {
public Transform onHand;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetMouseButton(1)){
this.transform.position = onHand.position;
}
}
void OnMouseDown () {
GetComponent<Rigidbody>().useGravity = false;
this.transform.position = onHand.position;
this.transform.parent = GameObject.Find("Player").transform;
}
void OnMouseUp () {
this.transform.parent = null;
GetComponent<Rigidbody>().useGravity = true;
}
}
So far it kind of works.. I've some trouble picking up my object, it does not always let me. I have to click a couple of times, before it actually gets a hold on the object. When it does, the objects starts flying upwards for some weird reason i do not understand. I still have a hold on it, i can still walk around with it and as soon as i let go it falls down.
Based on the limited amount of data you have shown, I can suggest some common things to check / try. If you update with more details I'll try and help you further.
What value is assigned to your public Transform onHand variable?
Is there a reason why you are doing click detection in two places? Try deleting the lines inside the "Update" method.
The OnMouseDown method should be enough. However, for OnMouseDown to work, your object needs to have a physics collider setup. Check to see if you have a collider and that it's dimensions match what you would expect.
For debug purposes, try setting "isKinematic" to true on your pickup's rigidbody (from the inspector, permanently) this should disable gravity and other forces from moving your pickup object, so you can test out the rest of your code.
Also when you pick it up, set it's transform position to 0,0,0
This should make the object follow the player at the exact center spot of the player object.
Once you verify this works correctly, put features back in and see if any of them break the setup.
Start by setting the position back from 0,0,0 to onHand and then check if the pickup actually appears on the player's hand.
If not, check the value of the onHand variable.
Then you can turn off isKinematic and see if everything is still okay.
As a side note:
You might want to keep using isKinematic instead of disabling gravity. You could set it as kinematic when it's picked up to stop any forces from affecting the pickup's position, while the pickup itself will still have an effect on other rigidbodies.
Then when you drop it on mouse up, just turn off isKinematic again