2
\$\begingroup\$

I'm working on a Breakout clone and I decide to use files as method to load level layouts. The file is something like this:

N,N,N,N,N

N,N,N

N,N,N

Only indicates what type of brick I'll instantiate, the initial positions to set this are in the WallBuilder.cs shown next. But I got a problem when I use my script, because the bricks doesn't appear in the rights position, they look moved and translated, and in the start moment, they move, but I don't understand why, I leave you a screenshot of the game when starts:

Level Start

And the configuration of the prefabs of my brick:

Prefabs Brick Configuration

Also, I leave you the WallBuilder.cs, which constructs the level based on the size of the screen and puts each brick next to each other:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.IO;

public class WallBuilder : MonoBehaviour
{
    public float xOffset = 0.31f;
    public float yOffset = 0.15f;
    public GameObject level;
    private List<List<string>> filedata;
    private Dictionary<string, string> prefabMap;

    // Use this for initialization 24
    void Awake ()
    {
        readFile("./Assets/" + Application.loadedLevelName + ".lyt");
        initPrefabMap();
        placeBricks();
    }

    // Update is called once per frame
    void Update ()
    {

    }

    private void initPrefabMap()
    {
        prefabMap = new Dictionary<string, string>();
        prefabMap.Add("F","FastBallsBrick");
        prefabMap.Add("I", "InverseBrick");
        prefabMap.Add("M", "MultipleBallsBrick");
        prefabMap.Add("U", "NonDestroyableBrick");
        prefabMap.Add("N", "NormalBrickPrefab");
        prefabMap.Add("S", "SlowBallsBrick");
        prefabMap.Add("X", "XResBrickPrefab");
        prefabMap.Add("XX", "XXResBrickPrefab");
    }

    private void readFile(string filename)
    {
        TextAsset sr = Resources.Load("Level2") as TextAsset;
        filedata = sr.text.Split('\n').Select(s=>s.Split(',').ToList()).ToList();
    }

    private void placeBricks()
    {
        Camera mainCamera = tk2dCamera.Instance.ScreenCamera;

        float halfWidth = mainCamera.aspect * (mainCamera.orthographicSize/100);
        float tempYOffset = (mainCamera.orthographicSize/100) - yOffset - 0.5f;
        foreach (var data in filedata)
        {
            float tempXOffset = -halfWidth + xOffset;
            foreach (var item in data)
            {
                if (tempXOffset < halfWidth - xOffset)
                {
                    instantiateBrick(item,tempXOffset, tempYOffset);
                }
                else
                {
                    break;
                }
                tempXOffset += xOffset;
            }
            tempYOffset -= yOffset;
        }
    }

    private void instantiateBrick(string type,float xOffset,float yOffset)
    {
        string item = type.Trim ();
        if (prefabMap.ContainsKey (item)) {
            GameObject.Instantiate (Resources.Load (prefabMap [item]), new Vector3 (xOffset, yOffset, 0), Quaternion.identity);
        }
    }
}

Also, I leave you the collision exit method of the brick, just in case:

   void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Player") {
            brick.addHits ();
            if (brick.getCurrentHits () == brick.getNeededHits ()) {

                Brick.ObjectBrick objectBrick = brick.getObject();

                if (objectBrick != Brick.ObjectBrick.NONE) {
                    String objectBrickStr = StringUtils.GetStringValue(objectBrick);
                    Instantiate(Resources.Load(objectBrickStr), gameObject.transform.position, gameObject.transform.rotation);
                }

                int totalPoints = brick.getPoints()*brick.getCurrentHits();

                GameObject gameObjectGM = GameObject.Find("GameManager");
                GameManager gameManager = (GameManager) gameObjectGM.GetComponent(typeof(GameManager));
                gameManager.addScore(totalPoints);
                gameManager.minusBrick();

                Destroy(gameObject);
            }
        }
    }

I have tried different things:

  1. I harcoded the positions for the blocks, but after the Instantiate method in the WallBuilder.cs, they are set in other positions, maybe I'm wrong, but could be something about physics between the objects.

  2. After that I removed the rigidbody2D of the prefab bricks, and they start to overlap each other no matter the offset I defined in the WallBuilder.cs. (I'll upload a screenshot of this later).

  3. After those tests I notice that this problem doesn't occur when each row of my level has the exact amount of bricks, if I add one in any row, that problem occurs when I start the game.

I hope someone help me out.

Thank you

\$\endgroup\$
  • \$\begingroup\$ What have you tried? Did you compare the block's positions with what you're setting them to in the file? Have you tried setting a block to a known hard coded position and compared that to where it was actually set in game? There's lots of things you should have tried already and I don't see any effort described here. \$\endgroup\$ – MichaelHouse Sep 24 '14 at 19:00
  • 1
    \$\begingroup\$ @oscar.rpr did you try freezing the position? (not sure if it's avaialbe in RigidBody2D never used it.) \$\endgroup\$ – concept3d Sep 26 '14 at 19:51
  • 1
    \$\begingroup\$ Do you want the physics engine to move the bricks around? If not check "Is Kinematic". \$\endgroup\$ – Kelly Thomas Sep 27 '14 at 3:58
  • 1
    \$\begingroup\$ @concept3d yo give a really good direction to work out, and I solved this problem thanks to the extra help of Kelly Thomas. I only need to check Is Kinematic because the physics engine doesn't move bricks around with that configuration. \$\endgroup\$ – oscar.rpr Sep 29 '14 at 14:39
  • 1
    \$\begingroup\$ @Kelly Thomas, if you want put that like an answer and I'll give you the bounty. \$\endgroup\$ – oscar.rpr Sep 29 '14 at 14:40
3
+50
\$\begingroup\$

Rigidbodies can be said to operate in two modes:

Non-Kinematic has physics driven movement, the physics engine will consider any forces brought to bear on the object to calculate and apply changes to velocity, rotation and position.

Kinematic lacks physics driven movement, the physics engine will not cause this object to move and any forces on the object will be disregarded. These objects can be moved through code by directly manipulating the Transform if required.

One important point to be mindful of is that the physics engine is optimized such that it will not detect collisions between two Kinematic Rigidbodies.

If your ball is a Non-Kinematic Rigidbody and you want the bricks to remain stationary then I recommend setting the bricks to Kinematic.

|improve this answer|||||
\$\endgroup\$
3
\$\begingroup\$

A few things catch my attention off the bat. First:

    filedata = sr.text.Split('\n').Select(s=>s.Split(',').ToList()).ToList();  

Feels highly dubious to me. Are you sure this is doing what you expect it do be doing?
Second:

    float halfWidth = mainCamera.aspect * (mainCamera.orthographicSize/100);  
    float tempYOffset = (mainCamera.orthographicSize/100) - yOffset - 0.5f;  

Is just begging for integer division issues. I'd toss an 'f' on each of those 100s, just to be explicitly clear that you are indeed doing float division.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ I thought the same at first. But I checked to find out that orthographicSize is float. So I assume 100 will be promoted to float. \$\endgroup\$ – concept3d Sep 26 '14 at 21:23
  • \$\begingroup\$ With the way unity handles floats, I would not assume any promotion \$\endgroup\$ – Habitablaba Sep 26 '14 at 21:29
  • 3
    \$\begingroup\$ In C#, an integer will become a float in a float/integer division. Unity does not alter the language or runtime that much. \$\endgroup\$ – user1430 Sep 26 '14 at 22:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.