I was looking for a way to make my gameobject not overlap to the another gameobject but all the solutions are talking about Rigidbody..
when i want to do it in script only without rigidbody, is it possible ? I have a cube with this scale (3,1,1) I make him rotate around itself but i got the overlap problem because his x scale is 3
Is there anyway to make him move and back automatically to avoid the red gameobject?
image
you can use this method
GameObject myDraggedGO; // parent
private IEnumerator OverLapChecker(float delay)
{
yield return new WaitForSeconds(delay);
Collider2D[] colls = new Collider2D[3];
List<int> nums = new List<int>();
foreach (var tile in myDraggedGO.GetComponentsInChildren<Rigidbody2D>())
{
nums.Add(Physics2D.OverlapCircleNonAlloc(tile.transform.position, 0.5f, colls));
}
if (nums.Contains(2))
{
myDraggedGO.transform.position = _startpositionOnDrag;
}
}
Related
I am attempting to create a 2d top-down car racing game. This game will have a random road map each time the player plays the game. I have thought about doing this in two different ways: A tilemap, or just generate the roads by placing different prefabs (straight roads, turns, etc). I have decided to go with the prefab route.
The way I believe it should work is to have prefab square "tiles" which have their own colliders set on the edges so I can tell if a player goes off the track in which case they blow up. I would have a MapGenerator Script which will generate an initial random map by keeping track of the last tile placed (including its location and road type: left turn, straight, right, etc). This script will then keep adding onto the road randomly as the player gets closer and closer to the end which makes it an infinite road.
I just want to know if this is just not efficient or if I am thinking of this completely wrong.
Here are a couple of images showing my road tiles which I made in photoshop and then one prefab for a straight road (take note of the colliders on its edges).
A similar game to one I want to make is Sling Drift which I can provide the link if you want. I don't know the policy on adding links to forum chat.
Also, here is my code for the map generator:
//Type of tyle, types are normal (straight road or horizontal road) and turns
public enum MapTileType
{
NORMAL,
N_E,
N_W,
S_E,
S_W
}
//structure for holding the last tile location and its type.
public struct TypedTileLocation
{
public TypedTileLocation(Vector2 pos, MapTileType tyleType)
{
m_tileType = tyleType;
m_position = pos;
}
public Vector2 m_position;
public MapTileType m_tileType;
}
public class MapGenerator : MonoBehaviour
{
//Map Tiles
public GameObject m_roadTile;
public GameObject m_turnNorthWestTile;
//holds all the tiles made in the game
private List<GameObject> m_allTiles;
//Map Tile Widths and Height
private float m_roadTileWidth, m_roadTileHeight;
//Used for generating next tile
TypedTileLocation m_lastTilePlaced;
private void Awake()
{
//store the initial beginning tile location (0,0)
m_lastTilePlaced = new TypedTileLocation(new Vector2(0,0), MapTileType.NORMAL);
//set height and width of tiles
m_roadTileWidth = m_roadTile.GetComponent<Renderer>().bounds.size.x;
m_roadTileHeight = m_roadTile.GetComponent<Renderer>().bounds.size.y;
m_allTiles = new List<GameObject>();
}
// Start is called before the first frame update
void Start()
{
SetupMap();
}
void SetupMap()
{
//starting at the beginning, just put a few tiles in straight before any turns occur
for (int i = 0; i < 6; ++i)
{
GameObject newTempTile = Instantiate(m_roadTile, new Vector2(0, m_roadTileHeight * i), Quaternion.identity);
m_lastTilePlaced.m_tileType = MapTileType.NORMAL;
m_lastTilePlaced.m_position.x = newTempTile.transform.position.x;
m_lastTilePlaced.m_position.y = newTempTile.transform.position.y;
m_allTiles.Add(newTempTile);
}
//now lets create a starter map of 100 road tiles (including turns and straigt-aways)
for (int i = 0; i < 100; ++i)
{
//first check if its time to create a turn. Maybe I'll randomly choose to either create a turn or not here
//draw either turn or straight road, if the tile was a turn decide which direction we are now going (N, W, E, S).
//this helps us determine which turns we can take next
//repeat this process.
}
}
void GenerateMoreMap()
{
//this will generate more map onto the already existing road and then will delete some of the others
}
// Update is called once per frame
void Update()
{
}
private void OnDrawGizmos()
{
}
}
Thanks!
Have you tried splines? They let you make curvy paths like race tracks easily. If not, here is a video that might help: https://www.youtube.com/watch?v=7j_BNf9s0jM.
I wanted to make a vertically scrolling background with 3D assets (2D pictures works fine, but i wanted the cool lighting effect), and i kept failing doing something i though would be so simple.
so here's my current progress:
public Vector3 target;
private Transform Top_Top_Left_Rescroll;
void Start (){
target = GameObject.FindGameObjectWithTag ("Top_Top_Left_Rescroll").GetComponent<Transform>();
}
void Update () {
if (gameObject.transform.position.y <= -12) {
gameObject.transform.position = new Vector3 (target.x, target.y, target.z);
}
}
}
The object resets it's position to 0 after the if statement (the rotation and scale weren't affected), and i ran out of ideas to do what i want.
You are passing a Transform to a Vector3.
try :
target = GameObject.FindGameObjectWithTag("Top_Top_Left_Rescroll").transform.position;
ps: I'm not sure if you really want your target position to never change, but you are passing it's value during Start() so you will always place your gameObject in every frame at the same initial position.
I have following problem with my Unity3D project. I will try to describe it on images.
So I want to merge to objects into 1. When object 1 and 2 collide, then they merge (object 2 became child of object 1). In practice I made it when bolt in object 1 (this blue "something" is bolt) collide with object 2, then they should merge. And I want to position object 2 on top of object 1 (saying top I mean where the red lines are, right image in second picture). So I decide to set localPosition of second object to be equal to bolt's localPosition (bolt is child of object 1 too). But that was wrong (second image, left side). So I get idea that I should add half of second object's height to one of his axis. But still it isn't perfect. And also I don't know to which axis I should add it. And should I use localPosition or normal position when I'm adding this half of height?
My code:
void OnTriggerEnter(Collider c) {
if(transform.IsChildOf(mainObject.transform)) {
childObject.transform.SetParent (mainObject.transform);
childObject.transform.localPosition = boltObject.transform.localPosition;
childObject.transform.position = new Vector3 (childObject.transform.position.x, childObject.transform.position.y, (float)(childObject.transform.position.z + childObject.GetComponent<Renderer>().bounds.size.z));
}
}
I have to add that objects can have different size, so I can't just add a number, it must be flexible. I will be very grateful for any help.
EDIT:
This my whole code:
using UnityEngine;
using System.Collections;
public class MergeWithAnother : MonoBehaviour {
public GameObject mainObject;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider c) {
if(transform.IsChildOf(mainObject.transform)) {
if (c.gameObject.name == "holeForBolt" && c.gameObject.transform.parent.gameObject != mainObject) {
Destroy (c.gameObject.transform.parent.gameObject.GetComponent("MouseDrag"));
Destroy (c.gameObject.transform.parent.gameObject.GetComponent("RotateObject"));
c.gameObject.transform.parent.gameObject.transform.SetParent (mainObject.transform);
c.gameObject.transform.parent.gameObject.transform.localPosition = gameObject.transform.localPosition;
c.gameObject.transform.parent.gameObject.transform.position = new Vector3 (c.gameObject.transform.parent.gameObject.transform.position.x, c.gameObject.transform.parent.gameObject.transform.position.y, (float)(c.gameObject.transform.parent.gameObject.transform.position.z + c.gameObject.transform.parent.gameObject.GetComponent<Renderer>().bounds.size.z));
c.gameObject.transform.parent.gameObject.transform.localRotation = gameObject.transform.localRotation;
c.gameObject.transform.parent.gameObject.transform.localRotation = new Quaternion (360 + c.gameObject.transform.parent.gameObject.transform.localRotation.x, c.gameObject.transform.parent.gameObject.transform.localRotation.y, c.gameObject.transform.parent.gameObject.transform.localRotation.z, c.gameObject.transform.parent.gameObject.transform.localRotation.w);
Destroy (c.gameObject.transform.parent.gameObject.GetComponent<CapsuleCollider>());
Destroy (gameObject);
Destroy (c.gameObject);
CapsuleCollider cc = mainObject.GetComponent<CapsuleCollider>();
cc.height *= 2;
cc.center = new Vector3(0, 0, 1);
}
}
}
}
I will explain what that means:
MainObject is the 1st object in picture.
c.gameObject.transform.parent.gameObject is the 2nd object from
picture
gameObject is bolt (blue something in 1 object)
script is attached in bolt (blue something on picture)
just use the position of your first object and bounds.size:
vector3 posOfSecObject = new vector3(0,0,0);
posOfSecObject.y +=
FIRSTOBJECT.GetComponent().Renderer.bounds.size.y;
I used the Y axis, I don't know which one you need, just try ;) I used this code to build a house composed of floors
I have 2 Spheres in my scene. I want to be able to drag and drop my mouse from one sphere to the other, and have an indicator (a straight line for example) while dragging. After releasing the mouse button, I want to store in the first sphere the other sphere (as GameObject).
I need this in UnityScript, but I can accept C# ideas.
So far I have thought about onMouseDown event on the first Sphere, and then onMouseEnter to the other sphere, I'll store the data in some global variable (which I donno how to do yet) and in case of onMouseExit I'll just put the global variable as null.
Then onMouseUp on the first Sphere I'll store the global variable in the pressed object (the sphere).
Any tips and tricks on how to do it?
Assumptions/Setup
You're working in a 2D worldspace; the logic for dragging the object for this part of the solution would need changing.
Setting parent after click drag, referred to setting the object you didn't click to be the child of the parent you did click on.
The camera should be an orthographic camera; using a perspective camera will cause the dragging to not align with where you think it should be.
In order to make the dragging work, I created a quad that was used as the 'background' to the 2D scene, and put that on a new layer called 'background'. Then setup the layermask field to only use the background layer.
Create and setup a material for the line renderer, (I'm using a Particles/Additive shader for the above example), and for the parameters of the line renderer I'm using Start Width: 0.75, End Width: 0, and make sure Use World Space is ticked.
Explanation
Firstly setup the otherSphere field to be pointing to the other sphere in the scene. OnMouseDown and OnMouseUp toggle the mouseDown bool, that is used to determine if the line renderer should be updated. These are also used to turn on/off the line renderer, and set/remove the parent transform of the two spheres.
To get the position to be dragged to, I'm getting a ray based off of the mouse position on screen, using the method ScreenPointToRay. If you wanted to create add smoothing to this drag functionality, you should enable the if (...) else statement at the bottom, and set the lerpTime to a value (0.25 worked well for me).
Note; when you release the mouse, the parent is immediately set, as such both objects end up getting dragged, but the child will return to it's former position anyway.
[RequireComponent(typeof(LineRenderer))]
public class ConnectedSphere : MonoBehaviour
{
[SerializeField]
private Transform m_otherSphere;
[SerializeField]
private float m_lerpTime;
[SerializeField]
private LayerMask m_layerMask;
private LineRenderer m_lineRenderer;
private bool m_mouseDown;
private Vector3 m_position;
private RaycastHit m_hit;
public void Start()
{
m_lineRenderer = GetComponent<LineRenderer>();
m_lineRenderer.enabled = false;
m_position = transform.position;
}
public void OnMouseDown()
{
//Un-parent objects
transform.parent = null;
m_otherSphere.parent = null;
m_mouseDown = true;
m_lineRenderer.enabled = true;
}
public void OnMouseUp()
{
//Parent other object
m_otherSphere.parent = transform;
m_mouseDown = false;
m_lineRenderer.enabled = false;
}
public void Update()
{
//Update line renderer and target position whilst mouse down
if (m_mouseDown)
{
//Set line renderer
m_lineRenderer.SetPosition(0, transform.position);
m_lineRenderer.SetPosition(1, m_otherSphere.position);
//Get mouse world position
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out m_hit, m_layerMask))
{
m_position.x = m_hit.point.x;
m_position.y = m_hit.point.y;
}
}
//Set position (2D world space)
//if (m_lerpTime == 0f)
transform.position = m_position;
//else
//transform.position = Vector3.Lerp(transform.position, m_position, Time.deltaTime / m_lerpTime);
}
}
Hope this helped someone.
I am trying to make the enemy spawning / movement system for a side scrolling game.
What is supposed to happen is the enemies are to spawn and move right until they collide with a specific object then they will travel in the opposite direction.
I have done research and asked question to get me this far:
I have made an enemy class and then made a list that can add more enemies and set their individual spawning positions. Then I have made an EnemyBlock class so I can set where the various collision objects will be (In this case they are just brick squares).
I am having some trouble
A. In making the enemies turn around when they leave the game screen.
And B. writing collision code for the enemies and enemyblocks as when I try and write collision code in the Game1.cs Update section under foreach (Enemy enemy in enemies) it doesn't pick the the enemyblock's rectangle. If that makes sense. Im sorry but I am pretty new to XNA code.
Game1.cs code
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Rectangle bounds;
List<Enemy> Enemies = new List<Enemy>();
List<EnemyBlock> Blocks = new List<EnemyBlock>();
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
Blocks.Add(new EnemyBlock(Content.Load<Texture2D>("02Brick"), new Vector2(50, 100)));
Enemies.Add(new Enemy(Content.Load<Texture2D>("Mario_Sprite"), new Vector2(100, 100), new Vector2(1, 0)));
Blocks.Add(new EnemyBlock(Content.Load<Texture2D>("02Brick"), new Vector2(500, 100)));
Blocks.Add(new EnemyBlock(Content.Load<Texture2D>("02Brick"), new Vector2(50, 200)));
Enemies.Add(new Enemy(Content.Load<Texture2D>("Mario_Sprite"), new Vector2(100, 200), new Vector2(1, 0)));
Blocks.Add(new EnemyBlock(Content.Load<Texture2D>("02Brick"), new Vector2(400, 200)));
foreach (Enemy enemy in Enemies)
{
enemy.bounds = new Rectangle((int)(enemy.position.X - enemy.texture.Width), (int)(enemy.position.Y - enemy.texture.Height), enemy.texture.Width, enemy.texture.Height);
}
foreach (EnemyBlock block in Blocks)
{
block.bounds = new Rectangle((int)(block.position.X - block.texture.Width), (int)(block.position.Y - block.texture.Height), block.texture.Width, block.texture.Height);
}
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
foreach (Enemy enemy in Enemies)
{
if (!GraphicsDevice.Viewport.Bounds.Contains(enemy.bounds))
{
enemy.velocity = -enemy.velocity;
enemy.position += enemy.velocity;
}
else
{
enemy.position += enemy.velocity;
}
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin();
foreach (Enemy enemy in Enemies)
{
spriteBatch.Draw(enemy.texture, enemy.position, Color.White);
}
foreach (EnemyBlock block in Blocks)
{
spriteBatch.Draw(block.texture, block.position, Color.White);
}
spriteBatch.End();
base.Draw(gameTime);
}
}
}
Enemy class code
class Enemy
{
public Texture2D texture;
public Rectangle bounds;
public Vector2 position;
public Vector2 velocity;
public Enemy(Texture2D Texture, Vector2 Position, Vector2 Velocity)
{
texture = Texture;
position = Position;
velocity = Velocity;
}
}
EnemyBlock class code
class EnemyBlock
{
public Texture2D texture;
public Rectangle bounds;
public Vector2 position;
public EnemyBlock(Texture2D Texture, Vector2 Position)
{
texture = Texture;
position = Position;
}
}
Your code seems to be very well structured and organized. Makes it a lot easier to be able to find any of these problems your having so thanks and keep your code organized. It's a good habit and it makes larger projects much easier.
Anyways I think I might have the answer to your problem.
The reason your rectangles aren't being picked up is because you are initializing the rectangles for your enemies and blocks in your load content method.
This is fine except that you don't appear to update the position of the rectangles. You update the velocity and position of the enemies and blocks though you check for collision with the bounding rectangles.
This means that your enemies will be able to move off screen and through objects because your the draw position has moved but the rectangle hasn't meaning it won't detect the collision.
I believe other problem is with specifying the rectangle position. I believe your code maybe a bit off but if it works fine then leave it. But if the collision detection is a little off then try the following. Your code
enemy.bounds = new Rectangle((int)(enemy.position.X - enemy.texture.Width), (int)(enemy.position.Y - enemy.texture.Height), enemy.texture.Width, enemy.texture.Height);
should look like
enemy.bounds = new Rectangle(enemy.position.X, enemy.position.Y, enemy.texture.Width, enemy.texture.Height);
based on how you are drawing your images.
The constructor of the rectangle specifies the top left corner's x, y position and the width/height of the rectangle. Rectangle r = new Rectangle(100, 100, 200, 200) creates a rectangle at 100, 100 and 200 wide and 200 tall.
This will match up with how you draw your enemies and blocks.
And lastly the collision code is fairly simple:
foreach(Enemy enemy in Enemies)
{
foreach(EnemyBlock block in Blocks)
{
if(enemy.bounds.Contains(block.bounds))
{
//what to do on collision
}
}
}
I hope this is all correct and helps.
I'm not proficient on XNA, anyway,
try removing negation, because the code looks like it will always reverse the velocity while not on viewport's edge
if (GraphicsDevice.Viewport.Bounds.Contains(enemy.bounds))
{
enemy.velocity *= -1;
}
enemy.position += enemy.velocity;
with this, the enemy velocity will reverse only when it reaches the boundary.
No need to put an else statement since the enemy will always be moving.
As for the collision with enemy blocks, here is a good tutorial from MSDN on making 2D side scrolling games like mario. CLICK HERE
in the tutorial everything is treated as a tile object on 2d array map and on update, it checks against a tile of the array where the enemy is currently standing (enemy's position)