Unity3D OnPointerClick is based on cam position? - c#

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.

Related

Tilemaps.SetTile method only partially working when in Update() method

I'm completely new (<1 week) to Unity, C# and game development generally. I'm starting out making a 2D isometric, grid-based CRPG and have hit a major wall with Unity's tilemaps.
I have a component which creates a tilemap tile underneath the parent GameObject using Tilemap.SetTile. As the GameObject moves around the grid, the tile should move with it and delete the previous tile. The tile can then create a moving obstacle node for pathfinding (which is working fine with static obstacles).
The problem is that the script actually does briefly work, just not for very long. If the GameObject moves along a path 'n' cells in a grid, the script will render 'n/2' cells every time the script is run, then stop working altogether. There's no error messages, freezing or anything, the tiles just aren't being drawn, and I know from logging in the console that the script is correctly tracking where the tiles should be drawn.
The obstacle script looks like this:
private void SetObstacleTile()
{
currentCell = obstacleMap.WorldToCell(transform.position);
if (currentCell != previousCell)
{
//set the new tile
obstacleMap.SetTile(currentCell, obstacleTile);
// erase previous
obstacleMap.SetTile(previousCell, null);
// save the new position for next frame
previousCell = currentCell;
Debug.Log(currentCell);
}
}
private void Update()
{
SetObstacleTile();
}
... and the movement currently looks like this:
void Update()
{
if (Vector3.Distance(transform.position, destination) > 0.01f)
transform.position = Vector3.MoveTowards(transform.position, destination, movementSpeed * Time.deltaTime);
}
My gut feeling is that it's something to do with how the Update() functions in the character movement and obstacle tiles component are interacting with each other but I don't have the experience to know how close I am to the problem. Any help with what could be causing this would be massively appreciated.

How come the Collider falls from the GameObject when a RigidBody is added?

I could really need some help with my GameObjects.
I am working on a game in which I want a pick-up Item to create a Physics Force explosion to blow away the enemies. I made a simple Bomb-Object to test this idea. I added a straightforward code, using a loop to collect all the colliders within its radius, to then addForce to these colliders. Now the code is working properly, but not all my GameObjects are reacting properly.
I looked into why this is, and I noticed that my Collider keeps falling away from the GameObject as soon as I add a RigidBody component to the object. The RigidBody is needed for the AddForce impact. When I remove the rb, the collider stays in place, but the object does not react to the Physics Force.
I added some images to illustrate what I mean:
Image of the Collider of the leaf sinking away..
Example image of objects which DO react to the AddForce.
I already tried to:
Copy/Paste all component settings from the reacting Cube and stone
Gameobjects to the Leaf Gameobject while disabling all other code
such as the c# scripts. The Collider & RB do not fall through the
floor but when Physics Force hits the Collider is blown away while
the GameObject keeps its position.
Try different GameObjects/Collider types.
Removed the water.
Play with amount of force/radius of the bomb.
Edited 'Tag' and 'Layerstyle' of GameObject.
The 'Explosion Code' is added below, however, I don't think the problem is in the code. I added the code to the Main Camera of my scene, and added a simple sphere as the 'bomb' GameObject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Explosion : MonoBehaviour
{
public GameObject bomb; //set the position of the explosion
public float power = 10.0f;
public float radius = 10.0f;
public float upForce = 0.0f;
private void FixedUpdate()
{
if (Input.GetKeyDown("space"))
{
print("space key was pressed");
Invoke("Detonate", 1);
}
}
void Detonate()
{
Vector3 explosionPosition = bomb.transform.position; //set the position of our explosion to the position of the bomb.
Collider[] colliders = Physics.OverlapSphere(explosionPosition, radius); //collects all colliders within the radius.
foreach (Collider hit in colliders) { //for each individual collider the following code is ran.
Rigidbody rb = hit.GetComponent<Rigidbody>(); //declare'rb' rigidbody. Get rb component from each collider
if (rb != null)
{
print("BOOM!");
rb.AddExplosionForce(power, explosionPosition, radius, upForce, ForceMode.Impulse); //add force to each collider
}
}
}
}
How do I make the Rigidbody, Collider and GameObject of the leaf hold onto each other like the standard 3D object 'cube', so that I can make these blow away with the Physics Force just like the other models?
Thank you for your time, I have been trying things and looking around on the Internet for hours now but can't seem to find any solution.
What happens if you add the rigidbody in stop mode and press play? Does it move away in a similar manner? This may, and is expected to happen, if your colliders intersect with each other. As soon as you add a rigidbody, they find themselves trapped in a serious collision.
If you don't want to modify the scene, you can fiddle with the collision matrix in project settings / physics

How to stop player from automatically jumping on a moving platform?

I made a moving platform that goes vertically top to bottom and then bottom to top and so on. Platform moves fine but placing my player on it makes my player unstable.
When platform moves from top to bottom, my player kinda bounces on it. When platform moves from bottom to top, it remain stable on the way but when it reaches top point, my player makes a jump by itself.
Its get even worse when i increase the speed of my platform. I don't know if its due to unity 2d physics effect or what. I have tried to use physics material 2D on my player object and platform by setting bounce to 0 and friction to 50 but nothing seems to work. Any one have idea how to disable physics effect of moving platform? Following is my code for moving platform:
public class BrickMoveVErtical : MonoBehaviour {
public Vector3 positionOne;
public Vector3 positiontwo;
public Vector3 nextposition;
/*Empty object is already made on unity editor and its parent of platform(Plank) and other
empty object "pointB". Point "B" is already mapped on editor and platform is set to go from
its original pos to point B */
public Transform plankTranform;
public Transform positionBTransform;
public float speed;
// Use this for initialization
void Start () {
positionOne = plankTranform.localPosition;
positiontwo = positionBTransform.localPosition;
nextposition = positiontwo;
}
// Update is called once per frame
void Update () {
move();
}
private void move() {
plankTranform.localPosition = Vector3.MoveTowards(plankTranform.localPosition,nextposition,Time.deltaTime*speed);
if(Vector3.Distance(plankTranform.localPosition,nextposition)<0.1)
{ changeMovementPlank(); }
}
void changeMovementPlank() {
nextposition = nextposition != positionOne ? positionOne : positiontwo;
}
}
I had similar problems with fast platforms in my game, the character would be left out in the air or slide off, depending on the direction of the platform.
I found a workaround for the problem by simply changing the character transform.parent to the platform it was jumping on, whenever the player exists the platform collider, simply return the players original transform.parent.
Note that this might cause other bugs or problems that will need to optimize, depending on your game that is.
You can use this code to set/unset the parent of a GameObject:
void OnTriggerEnter2D(Collider2D other)
{
if(other.gameObject.tag == "PlatformGroup")
player.SetParent(other.gameObject.transform)
}
void OnTriggerExit2D(Collider2D other)
{
if(other.gameObject.tag == "PlatformGroup")
player.SetParent(null);
}
What you should do is:
Create an empty GameObject, and you make your platform child of this
empty GameObject. Tag it as PlatformGroup.
You add the script to move the platform to this EmptyGame Object,
instead of using it in the platform itself.
Then add a collider to empty gameobject(PlatformGroup) and another to the Player. Set the one of the player as trigger.
Add the code above to your player controller.
Now, when the Player jumps over the Platform if will become a child of the same GameObject of the platform and they will move together without any deformations in the GameObject. Also when the player leaves the platform, walking or jumping out of it, it will stop being child.

Creating an endless spinner in Unity

I want a gameobject spinning around its y-axis. This spinner should have a initial movement direction and when colliding with something, it should change its direction.
I created a little picture to show what I mean, but I want the behaviour for a 3D game.
So I just started with the rotation of the spinner,
public class Spinner : MonoBehaviour
{
[SerializeField]
private float movementSpeed; // speed when moving
[SerializeField]
private float rotationSpeed; // speed when rotating
private Rigidbody rigid;
private Vector3 movementDirection; // the direction the spinner is moving
private void Start()
{
rigid = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
transform.Rotate(0, rotationSpeed, 0); // rotate the spinner around its y-axis
}
private void OnCollisionEnter(Collision col)
{
// set new direction
}
}
How can I move the spinner, that it moves along a direction and whenever it collides with something, it changes its direction. It should never stop moving or rotating.
I would like to point out a few things:
The Unity Physics Engine will make collisions to absorb part of the force which moves your spinner, so unless you keep adding "artificial" forces to the spinner it will eventually stop.
The "air friction" in your scene will also reduce the force of your
spinner, so it will slow it down. You should add a material to the
spinner which has 0 Dynamic Friction
Based on the comment you left in #reymoss' answer, you may consider
to add the bouncy material to the walls, and not to the spinning
GameObject.
To sum up, the issue here is if you want a GameObject to bounce against a wall using the Physics Engine, the object will eventually stop, because some of the forces will be absorbed in each collision. That means you will need to keep adding external forces every time a collision takes place, to keep it moving endlessly.
Something you can try is,
1- Add a bouncy material to the walls and remove the dynamic friction of your spinner. In the following link you can learn about this:
https://docs.unity3d.com/Manual/class-PhysicMaterial.html
2- Add to the Spinner a Collider, so when it detects a collision with a wall (you can tag the walls as so for example) add an additional force to the spinner in the direction it is already moving, so it will compensate the energy lost during the collision.
void OnTriggerExit(Collider other) {
if(other.tag == "wall") {
rigidbody.AddForce(rigidbody.velocity.normalized * Time.deltaTime * forceAmount);
}
}
The idea is to let the Engine decide the direction of the Spinner after the collision with the wall, and as soon as the GameObject leaves the trigger, you add an additional force in the current direction.
Then you can play with the Bounciness of the wall's material and with the forceAmount, until your spinner moves as you have in mind.
Note: Since you will have 2 materials, one in the walls and another in the spinner, maybe playing with the Friction Combine and Bounce Combine you will be able to avoid the force lost during collisions, so you will not need to add the external force I mention in the second step. However I have never tried this.
Let me know if it works. I can't try myself the solution until I arrive home.
If you give the object an initial velocity, attach a collider, create and assign a Physics Material 2D to the collider (to apply bounciness), and attach Colliders to the walls, you can have it bounce around with minimal code.
private void Start()
{
rigid = GetComponent<Rigidbody>();
rigid.velocity = new Vector3(2f, 3f, 1f) // initialize velocity here
}

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