In my game application, many child are added on main scene at run time andI want to give zIndex to a new child at run time but it is not taken into account. To give zIndex to the child I use code like :
mySprite.setZIndex(1);
But if I refresh the main scene at run time, then the child will take its zIndex properly. For refreshing the main scene, I use the code below :
mainScene.sortChildren();
But if I use the above code at run time, then it gives jerk to all child and you know its looks very bad ! Then, how to sort main scene children without jerk ?
Edit
I try to explain my issue with code and comments. In the code below, three methods : one method adds animated sprites into the main scene and one draw line method draw line into the main scene and my animsprite move on the line because line zIndex is 2 and myAnimSprit zIndex 3 so. But after every 5 seconds, I want to update z Index of animsprite like 1 in this example so line is on my animSprite that is done by changeZIndex method and it called by timer.
public class TouchPark extends BaseGameActivity {
private AnimatedSprite animSprite;
private Scene mainScene;
// load engine and load all resoureces here
#Override
public Scene onLoadScene(){
mainScene = new Scene();
createTimerHandler();
addAnimatedSprite()
}
public void addAnimatedSprite(){
animatedSprite = new AnimatedSprite(- mTextureRegion.getWidth(), - mTextureRegion.getHeight(), mTextureRegion.deepCopy());
animSprite.setZIndex(3);
animSprite.setPosition(initX, initY);
mainScene.attachChild(animSprite);
}
public void drawLine(ArrayList<Float> xList , ArrayList<Float> yList){
float x1 = xList.get(xListLength - 2);
float x2 = xList.get(xListLength - 1);
float y1 = yList.get(yListLength - 2);
float y2 = yList.get(yListLength - 1);
Line line = new Line(x1, y1 , x2 ,y2 , lineWidth);
line.setZIndex(2); //my sprite move on the line so that line zIndex is 2 and animSprite zIndex is 3
line.setColor(1, 0, 0);
mainScene.attachChild(line);
}
public void changeZIndex(){
animSprite.setZIndex(1); // now i want line is on the my animSprite so i changed zIndex of line
//but here it will not change zIndex of my animsprite at runTime
//but if i write below code then it will get effect
mainScene.sortChildren();
//but above code update not only one aimSprite but also all sprite that are presents on the mainScene
//and it look like all chilrens get jerk
}
public void createTimerHandler(){
mGeneralTimerHandler = new TimerHandler(5.0f, true, new ITimerCallback() {
public void onTimePassed(TimerHandler pTimerHandler) {
changeZIndex();
}
getEngine().registerUpdateHandler(mGeneralTimerHandler);
}
}
first load all the resources in your Scene.
After that implement below line..
GameActivity.activity.getEngine().setScene(yourScene);
user cannot view the scene till you call above line.
So that it wont show that jerks.
Intialize an Entity with highest Zorder .Then add all dynamically created sprites to his entity. If it is not cleared then post the code
Related
I am trying to add 100 dynamically created buttons to a scroll view in Unity, but I have a problem letting the scroll view automatically adjust the width of the buttons to match the width of my screen.
When I tried to add the buttons manually it worked fine , but when I do this by code I get another results.
The code I am using :
public GameObject button;
public GameObject scrollviewcontents;
void Start()
{
for (int i =0; i<=100;i++) {
GameObject dbutton = Instantiate(button);
dbutton.name = i.ToString();
dbutton.transform.parent = scrollviewcontents.transform;
}
}
and The results I get :
Results
Results with comments
I just want the buttons to look like as they are added manually, any help ???
By default when instantiating an object the object keeps the same world space position, rotation and scale as before. try this instead:
dbutton.transform.SetParent(scrollviewcontents.transform, false);
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 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
How can I get the actual position of an object in a grid layout? In my current iteration symbolPosition keeps returning 0,0,0.
public void OnPointerClick (PointerEventData eventData)
{
// Instantiate an object on click and parent to grid
symbolCharacter = Instantiate(Resources.Load ("Prefabs/Symbols/SymbolImage1")) as GameObject;
symbolCharacter.transform.SetParent(GameObject.FindGameObjectWithTag("MessagePanel").transform);
// Set scale of all objects added
symbolCharacter.transform.localScale = symbolScale;
// Find position of objects in grid
symbolPosition = symbolCharacter.transform.position;
Debug.Log(symbolPosition);
}
The position value wont be updated until the next frame. In order to allow you to make a lot of changes without each one of them causing an entire recalculation of those elements it stores the items that need to be calculated and then updates them at the beginning of the next frame.
so an option is to use a Coroutine to wait a frame and then get the position
public void OnPointerClick (PointerEventData eventData)
{
// Instantiate an object on click and parent to grid
symbolCharacter = Instantiate(Resources.Load ("Prefabs/Symbols/SymbolImage1")) as GameObject;
symbolCharacter.transform.SetParent(GameObject.FindGameObjectWithTag("MessagePanel").transform);
// Set scale of all objects added
symbolCharacter.transform.localScale = symbolScale;
StartCoroutine(CoWaitForPosition());
}
IEnumerator CoWaitForPosition()
{
yield return new WaitForEndOfFrame();
// Find position of objects in grid
symbolPosition = symbolCharacter.transform.position;
Debug.Log(symbolPosition);
}
This may not have been in the API when this question was asked/answered several years ago, but this appears to work to force the GridLayoutGroup to place child objects on the frame in which child objects are added, thus removing then need for a coroutine.
for(int i = 0; i < 25; i++){
GameObject gridCell = Instantiate(_gridCellPrefab);
gridCell.transform.SetParent(_gridLayoutTransform,false);
}
_gridLayoutGroup.CalculateLayoutInputHorizontal();
_gridLayoutGroup.CalculateLayoutInputVertical();
_gridLayoutGroup.SetLayoutHorizontal();
_gridLayoutGroup.SetLayoutVertical();
From here, you can get the positions of the 'gridCells' same frame.
There is another function, which seems like it should fulfill this purpose, but it isn't working for me. The API is pretty quiet on what exactly is going on internally:
LayoutRebuilder.ForceRebuildLayoutImmediate(_gridLayoutTransform);
I have just started unity. I have 4 Images(sprites) aligned in a grid.
As soon as i touch the particular chocolate, its texture changes[I wrote a code for that]. There is a button on screen.After pressing the button, I want to move only those chocolates whose texture has been changed.
I know the following move code but i don't know how to use it here.
void Update () {
float step=speed*Time.deltaTime;
transform.position=Vector3.MoveTowards(transform.position,target.position,step);
}
I just don't know to move that particular sprite whose texture is changed. Thanks
Do you want to be moving the sprites over the course of a duration or instantly?
If it's over the course of a duration I suggest you use Lerp. You can Lerp between two Vector.3's in a time scale. Much cleaner and once learned a very useful function.
Code examples below:
http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html
http://www.blueraja.com/blog/404/how-to-use-unity-3ds-linear-interpolation-vector3-lerp-correctly
However if you want to move it instantly. This can be done very easily using the built in localPosition properties which you can set in or outside the object.
Set your changed sprites Bool moved property (create this) to true on click (if you're using Unity 4.6 UI canvas then look at the IClick interfaces available for registering mouse activity in canvas elements) and then when you press the button, loop through a list in a handler file which contains all your button texture objects and move those that the moved property is set to true for.
foreach(GameObject chocolate in chocolateList)
{
if (chocolate.moved == true)
{
gameObject.transform.localPosition.x = Insert your new x position.
gameObject.transform.localPosition.y = Insert your new y position.
}
}
However please do clarify your intentions so I can help further.
EDIT 1:
I highly suggest you make your sprites an object in the canvas for absolute work clarity. This makes a lot of sense as your canvas can handle these type of things much better. Use Image and assign your image the sprite object (your chocolate piece), define it's width and height and add a script to it called "ChocolatePiece", in this script create two public variables, bool moved and int ID, nothing else is required from this script. Save this new object as your new prefab.
Once you've done this in a handler script attached to an empty gameobject in your canvas make a list of gameobjects:
List<GameObject> chocolatePieces = new List<GameObject>();
You'll want to at the top of your handler script define GameObject chocolatePiece and attach in your inspector the prefab we defined earlier. Then in Start(), loop the size of how many chocolate pieces you want, for your example lets use 4. Instantiate 4 of the prefabs you defined earlier as gameobjects and for each define their properties just like this:
Example variables:
int x = -200;
int y = 200;
int amountToMoveInX = 200;
int amountToMoveInY = 100;
Example instantiation code:
GameObject newPiece = (GameObject)Instantiate(chocolatePiece);
chocolatePieces.Add(newPiece);
newPiece.GetComponent<ChocolatePiece>().ID = i;
newPiece.transform.SetParent(gameObject.transform, false);
newPiece.name = ("ChocolatePiece" + i);
newPiece.GetComponent<RectTransform>().localPosition = new Vector3(x, y, 0);
From this point add to your positions (x by amountToMoveInX and y by amountToMoveInY) for the next loop count;
(For the transform.position, each count of your loop add an amount on to a default x and default y value (the position of your first piece most likely))
Now because you have all your gameobjects in a list with their properties properly set you can then access these gameobjects through your handler script.