Unity - Deleting other instances spawning on top of another, but keeping the original - unity3d

So, I am working on some level generation stuff in Unity, and I have some cubes spawning around the world. The way I have it working right now, is that each floor tile checks if there is 'air' around it and if so, it spawns a wall. But, if I have a situation where this is an air block between two floors, it'll spawn two walls.
Is there a way I can check if there is multiple in the same position, but keep one from destroying?
Thanks!
p.s Also worth nothing, I place the walls using Raycasts, so the floor will check in 4 directions using one hit. I figure it's checking all 4 directions without stopping when it places a cube. So, may be an issue...

U can try making a overlapsphere where the raycast hits, that way all the objects in a certain radius get detected (so also objects that are in each other)
void GetWalls(Vector3 raycastTargetPosition, float radius)
{
Collider[] hitColliders = Physics.OverlapSphere(center, radius);
int i = 0;
while (i < hitColliders.Length)
{
hitColliders[i].SendMessage("AddDamage");
i++;
}
}

Related

Unity - Blocking character from walking off ledges

I don't want my player to be able to walk off ledges. I did this by shooting a single raycast downwards in front of the player, and if ground is NOT hit, then ignore input.
However this is jarring, especially if you diagonally walk along an edge you just completely stop, rather than 'slide' along it.
So I thought I could add two raycasts, one per side to detect which side the ledge is, then allow movement (or steer) the player as applicable.
The problem is I'm not sure how to proceed from here. I'm using a character controller for movement, my current code is like:
velocityXZ = velocity;
velocityXZ.y = 0; // we deal with gravity elsewhere
velocityXZ = inputDir * playerSpeed;
if (facingDropLeft || facingDropRight) {
velocityXZ.x = 0;
velocityXZ.z = 0;
}
velocity = new Vector3(velocityXZ.x, velocity.y, velocityXZ.z);
// handle gravity
charController.Move(velocity * Time.deltaTime);
Could anyone offer some insights into what direction to look into, or methods I will need?
I think that if you want to accomplish an enjoyable result you should use invisible walls. I think that probuilder can help you.
This is the approach I would have with this type of problem.
Use boxes to make wall than turn off the mesh renderers this will make invisible walls

How to create a unity event to determine distance between objects, and do something when distance is small enough?

I'm trying to use the EventManager and according Events to calculate the distance between objects, and to do something when enough objects are close to the target.
I watched video's on YouTube and searched for examples on Google, but I couldn't find something that looks like what I want. Of course I also watched the explanation videos of Events in general, but I just don't get it. They are all English, which is not my native language, this makes it difficult to understand. So, also sorry for any grammar mistakes. They often talk so fast. So please don't think I'm lazy, I have searched for hours but I just don't get it.
I have one target object, and several enemy objects. This enemy objects have the tag 'Enemy'. The target object can move. I made a coroutine, so when the target moves, the enemies follow, until a distance of 0.5. But from the moment that they reached the distance of 0.5, the enemies won't move anymore. Instead they should also follow the target when they already reached their target position. So to prevent this, I changed the while(Vector3.Distance(transform.position, target.position) > 0.5f) in while 1 > 0, (so just always) and I deleted the part of the code that was about 'after the while loop'. But this is probably not the right way.
So, in short, I want to make an Event that keeps track of when enemies reaches or loses their target position. When three enemies are on their target position, I want to make them blue.
Could anyone show me how I can do this? I don't get it now, but when I see how it works I can use this for more events in the game.
I think You can use trigger collider, just make it bigger then your target object, then do all you want about enemies in methods OnTriggetEnter, OnTriggerStay
As an another technique you can use raycasts. Raycasts will provide you more performance than colliders.
You can locate your raycasts in your target position, in case your raycast hit the enemy then make them blue. For Example;
public LayerMask enemyLayer;
bool isTouch = false;
public bool isTouched(){
if (Physics.Raycast(transform.position,-Vector3.up,1f,enemyLayer)) {
isTouch = true;
return isTouch ;
}
return !isTouch ;
}

RaycastHit2D vs OnTriggerEnter2D

In my game you can use, axes, pickaxes, hoes, etc. Each to gather a different type of material (ore, wood, crops, etc).
My old system I just set a tiny collider on the tile in front of my player, and then in OnTriggerEnter2D on my nodes, trees, farm-tiles, etc. I checked what category of my Active Item that was entering (below example on my mining-nodes):
void OnTriggerEnter2D(Collider2D other)
{
if(other.gameObject.CompareTag("ActiveItem"))
{
ItemObject activeItemObj = GameManager.manager.activeItem.GetComponent<InventoryItem>().item;
if(activeItemObj.category == "pickaxe")
{
if (!isHit)
{
hit();
}
}
}
}
However this always felt kind of ugly, plus no matter how small the "front collider" is, there is always a chance to hit the tile intersection and hit as many as 4 tiles at the same time.
So instead I wanted to use RayCastHit2D, so I created these methods in my PlayerController Script:
public GameObject GetTileInFront()
{
Vector2 frontRay = new Vector2(transform.position.x + lastMove.x, transform.position.y + lastMove.y + 0.5f);
RaycastHit2D hit = Physics2D.Raycast(frontRay, Vector2.zero);
if (hit.collider != null)
{
Debug.Log("Target Position: " + hit.collider.gameObject.name);
return hit.collider.gameObject;
}
return null;
}
public void ActionInFront(string activeItem)
{
if (activeItem.Equals("pickaxe"))
{
if (GetTileInFront().CompareTag("Node"))
{
GetTileInFront().GetComponent<NodeManager>().hit();
}
}
}
Now I obviously need to create checks like this for every type of tool/tile.
Which leads me to my question:
Which of these 2 methods would be better for performance? I am completely self tought so I always worry I am making some obvious blunder that I cant see.
I definently like the precision of the RayCast better (even though it forces all my colliders to be at least 1x1 in size due to checking 1 tile in front).
Your solution looks OK to me!
Raycasts have the potential to be abused to the point where they're very expensive. The three things you'll want to be mindful of:
How long is the raycast? Keeping it under a tiles length should be good in your case.
What types of geometry is in your scene?: Mesh colliders can cause Raycasts to chug, but in a 2D game where I imagine everything is either a square or a circle you should be good.
How frequently do they occur? Calling a Raycast every frame can be rather expensive, but only calling it when your player is doing the action should be fine.
You mentioned that you were worried your solution will force your colliders to be at least 1x1, but there are ways to get around that. Right now what you're doing is just checking right at a point in front of your player. Instead you may want to consider casting a ray from the player in that direction and it could hit anything a long the way, even if it's smaller than a 1x1 tile. You can do this by changing the second argument of your raycast to something like this:
Physics2D.Raycast(transform.position, Vector2.up * .5f);
The Raycast function takes the point it will be shot from as the first argument, and the direction/length as the second argument (leaving the length 0 like did will just check the point at the first argument).
It's worth noting that if you try to do this with your current solution, all that will happen is that you're character will try to mine himself as it will be the first thing the ray hits! You'll need to add a LayerMask to your raycast to determine what the ray can and can't hit (or if you're lazy, just make sure the ray starts from a point outside the player's collision).

Unity3d - Need to hide a group of objects in the area

I've already tried depthmask shaders and examined some other ideas, but it seems like it doesn't suit me at all.
I'm making an AR game and I have a scene with a house and trees. All these objects are animated and do something like falling from the sky, but not all at once, but in sequence. For example, the house first, then trees, then fence etc.
(Plz, look at my picture for details) http://f2.s.qip.ru/bVqSAgcy.png
If user moves camera too far, he will see all these objects stucking in the air and waiting for their order to start falling, and it is not good. I want to hide this area from all sides (because in AR camera can move around freely) and make all parts visible only when each will start moving (falling down).
(One more screen) http://f3.s.qip.ru/bVqSAgcz.png
I thought about animation events, but there are too many objects (bricks, for example) and I can't handle all of them manually.
I look forward to your great advice ;)
P.S. Sorry for my bad english.
You can disable their(the objects that are gonna fall) mesh renderers and re active them when they are ready to fall.
See here for more details about mesh renderer.
Deactivate your Object. You might use the camera viewport coordinates to get a y position outside the viewport. They start on the bottom left of the screen (0,0) and go to the top right of the screen (1,1). Convert them to worldspace coordinates. Camera.ViewportToWorldPoint
Vector3 outsideCamera = Camera.main.ViewportToWorldPoint(new Vector3(0.5f, 1.2f, 10.0f));
Now you can use the intended x and z positions of your object. Activate it when you want to drop it.
myObject.transform.position = new Vector3(myObject.transform.position.x, outsideCamera.y, myObject.transform.position.z);
Another thing you could additionally do is scaling the object from very small to its intended size when it is falling. This would prevent the object being visible before falling when the users point the camera upwards.
1- Maybe you can use the Camera far clipping plane property.
Or you can even use 2 Cameras if you need to display let's say the landscape on one (which will not render the house + trees + ...) with a "big" far clipping plane and use a second one with Depth only clear flags rendering only the items (this one can have a smaller far clipping plane from what I understand).
2- Other suggestion I'd give you is adding the scale to your animation:
set the scale to 0 on the beginning of animation
wait for the item to be needed to fall down
set the scale to 1 (with a transition if needed)
make the item fall down
EDIT: the workaround you found is quite just fine too! But tracking only world position should be enough I think (saving a tiny amount of memory).
Hope this helps,
Finally, the solution I chose. I've added this script to each object in composition. It stores object's position (in my case both world and local) at Start() and listening if it changes in Update(). So, if true, stop monitoring and set MeshRenderer in on state.
[RequireComponent(typeof(MeshRenderer))]
public class RenderScript : MonoBehaviour
{
private MeshRenderer mr;
private bool monitoring = true;
private Vector3 posLocal;
private Vector3 posWorld;
// Use this for initialization
void Start()
{
mr = GetComponent<MeshRenderer>();
mr.enabled = false;
posLocal = transform.localPosition;
posWorld = transform.position;
}
// Update is called once per frame
void Update()
{
if (monitoring)
{
if (transform.localPosition != posLocal || transform.position != posWorld)
{
monitoring = false;
mr.enabled = true;
}
}
}
}
Even my funny cheap сhinese smartphone is alive after this, so, I guess, it's OK.

How to calculate the length of platform/object in Unity 5?

I'm new to Unity and after watching and reading some tutorials I'm now trying to make a simple 2D platformer kind of game. In the said game both enemies and player can jump to different platforms and traverse it like the old SnowBros game.
The problem I'm facing is related to programming the enemy movement. In my game there would be several types of enemies but generally for now there are two types, one that can jump from the platform and one that only walks upto the length of the platform, wait for 1 second then flip and walk backwards; meaning they don't get off the platform. Now this is an issue I'm having trouble with. I can't seem to find a way to calculate the length of the underlying current platform. I thought of using the collider.bound.min.x and max.x to come around the problem but the issue is I can't seem to find a simple way to reach the current platform's collider without fetching the script and then going through it.
Since, there would be many platforms of many different sizes and each platform is made up of a prefab of other platforms, it just doesn't seem like a workable solution to use the platform script and then traverse through it.
You can use Physics2D.Raycast to "sense" for collisions on a Ray. Imagine the enemy putting their toe one step forward, feeling if there is still solid ground, and then deciding whether to stop.
void Update()
{
Vector2 newPosition = transform.position + velocity * Time.deltaTime;
Vector2 downwardDirection = Vector2.down; // you may have to replace this with your downward direction if you have a different one
RaycastHit2D hit = Physics2D.Raycast(newPosition, downwardDirection);
if (hit.collider != null)
{
// solid ground detected
transform.position = newPosition;
}
else
{
// no ground detected. Do something else...
}
}
You can and should define the Layers your Raycast is supposed to hit, so it can ignore the enemy itself and avoid self-collision.
Well, I hope that you have prefabs of platform and in those prefabs put colliders at start and at end. You can specify layers and tags so that only enemy can detect those colliders and then you can detect tags on collision from enemy script and make your operation.
First create layers by opening Edit -> Project Settings -> Tags and Layers. Create two Layers
Create layers for enemy and enemyColliders and Goto Edit -> Project Settings -> Physics2D. Set collision matrix as EnemyCollider will collider with enemy only.
And your prefab will be looks like,
I hope this would help you.