I want to create a Magic Jewelry clone (Tetris + match 3) using Unity for mobile. So far, I've used UI elements such as UIImage, which serves as an individual block. I created a script that will give out random colors for the box. I then parented three blocks to an empty game object named GameObjectParent.
For the movement, I created another script that subtracts the GameObjectParent's anchoredposition.y every second. In terms of collision, I created a transparent UI Image that will serve as ground triggers that will stop the GameObjectParent's movement once it's entered.
My problem now is the matching of the colored blocks, and more importantly, Instantiating the GameObjectParent. I tried using out
RectTransform gRect = theCanvas.GetComponent<RectTransform>();
var groupH = Instantiate(GameObjectParent, new Vector3(0,0,0) , Quaternion.Euler(0,0,0));
groupH.transform.parent = theCanvas.transform;
groupH.transform.localScale = new Vector2(1, 1);
But it somewhat spawns out of place. I have a "startingblock" that is currently anchored on the canvas at (50, 810), which is where the spawned blocks should start. However, when I try this:
var groupH = Instantiate(GameObjectParent, new Vector2(80,810) , Quaternion.Euler(0,0,0));
The newly cloned and spawned GameObjectParent goes out of place (21392,8712398). I don't know what's happening. Even so, if I attach the Instantiate method on a keypress, it spawns two GameObjectParents at a time, the other being slightly tilted.
I also have no idea how to match the colors of the other blocks as well. I tried searching for similar game concepts like this for unity but to no avail. There are also no tutorials/guides/pointers etc. so I really have to discover it on my own. Any thoughts about this guys? And are there any pointers, guides, or anything that you could give me?
Much appreciated!
First, I wouldn't recommend using UI elements as game objects. We only use UI elements for, well, UI. Consider using sprites or quads instead. You can check Unity tutorials for making 2d games.
For matching, you can assign a code for each color. I usually use enums and bit masking.
Related
The problem:
I've been working on trying to create a 3D position in Worldspace based on a 2D face RGB face detection, similar to this Microsoft example. I am using Unity 2020.3.16f1, MRTK 2.8.2 and C# for the Unity scripts. I have been able to convert the C++ code shown in the link to C# with a lot of success. One final issue is accessing the HoloLens 2 origin SpatialCoordinateSystem to be used in the Transform between the camera's 2D coordinate system and the 3D worldspace system.
The SO question at this link asks a very similar question, and I have tried to use SpatialLocator.GetDefault().CreateStationaryFrameOfReferenceAtCurrentLocation().CoordinateSystem() as the answers suggest. I call this function in Unity's "Awake" method, to ensure it is set as early as possible, as shown below.
private void Awake()
{
worldSpatialCoordinateSystem = SpatialLocator.GetDefault().CreateStationaryFrameOfReferenceAtCurrentLocation().CoordinateSystem;
}
Problem is that, if the user's headset is moving while the application starts, I notice an offset in the 3D locations commensurate with the direction/position of the head when the application was starting. I have narrowed the problem down to the fact that the HL2 and Unity set an origin SpatialCoordinateSystem just before the function in Awake is called, accounting for the offset between what I expect and what I see.
What I've tried:
I have tried using some of the other solutions listed here as well. I cannot use UnityEngine.Windows.WebCam.PhotoCapture becuase of the way I am create still image captures, and (SpatialCoordinateSystem)Marshal.GetObjectForIUnknown(WorldManager.GetNativeISpatialCoordinateSystemPtr()) appears to be deprecated and unusable. Finally, I tried CreateStationaryFrameOfReferenceAtCurrentLocation(Vector3, Quaternion), and used the inverse of the current Camera.main position and rotation, hoping to compensate for the offset, but it did not appear to work (NumericsConversionExtensions is the UnityEngine-to-System.Numerics converver found here). That code is below.
worldSpatialCoordinateSystem = SpatialLocator.GetDefault().CreateStationaryFrameOfReferenceAtCurrentLocation(NumericsConversionExtensions.ToSystem(Camera.main.transform.position*-1),
NumericsConversionExtensions.ToSystem(Quaternion.Inverse(Camera.main.transform.rotation))).CoordinateSystem;
My question:
Is there either another way to access the origin spatial coordinates or possibly to compensate for the offset when the user is moving their head before Awake is called?
I spent 3 days working on the solution, and found one 1 hour after asking SO. For those who come here, use the code below, originally found here.
using Microsoft.MixedReality.OpenXR;
worldSpatialCoordinateSystem = PerceptionInterop.GetSceneCoordinateSystem(Pose.identity) as SpatialCoordinateSystem;
I added Sorting Group to diferent objects, and run very well, but I have a lot of problems with a fences ( look the picture ), I tried to add Sorting Group but didn't run well, so I tried modify Order in Layer with a script and I have the same problem, the other way that I tried are put manualy order in layer, and only run in front or background.
I passed a lot of hours thinking about this and test diferent things and I don't know what is the problem and solution.
I need help from the comunity to learn about this problem, probably the problem is the sprite I don't know, i'm really confused and disturbed.
Script is very simple and ineficient (only to test):
SpriteRenderer [] rendererFernce;
void Awake()
{
rendererFernce = FindObjectsOfType<SpriteRenderer>();
}
private void FixedUpdate()
{
foreach (SpriteRenderer renderer in rendererFernce)
{
renderer.sortingOrder = (int)(renderer.transform.position.y * -100);
}
}
Wrong Order in Layer
This might have different causes.
the fence is actually a 3d model: 3d models are shown on top of sprites if they are closer to the camera.
the center of the transforms are not where you think they are: the fence is very wide and different parts of it have different positions on the y 'axis'
you are changing the orderInLayer but not the sorting layers: layers have priority over orderInLayer
You can try to change this setting and see if it works instead of implementing it yourself:
Edit > Projecting Settings > Graphics > Transparency Sort Axis
setting it to (0, 1, 0)
You can find more information related to sorting here.
I'm trying to create a grid system for a 2D game. Not completely sure if I'll go with a hexagon-grid or isometric, but which shouldn't matter too much here. Basically, I'm trying to create a tower defense game where you deploy units instead of towers, and can move those as if you were playing a tactical game. The problem is that the tiles themselves are gonna be complex - there will be different types of terrain. Some units can only be deployed in X, and can't go through Y, that kind of thing. I also need the ability to add some logic to these tiles at will - who knows, maybe I want a special tile to give extra attack range to units above it, that kind of thing. The game must also "feel" like a grid - making things snap to the center of the tiles, as well as highlighting the tiles on hover and when moving/attacking.
Okay, this leads me to a pretty obvious route: I can create prefabs for the different types of tiles I need, add all the proprieties and logic as script components and create a grid class that instantiates each tile in the world. This works great, cause this way I have full control over everything - I can do whatever I want with the tiles, and I can also create a 2d matrix for their positions as I instantiate them. This way I can call tile[3, 6] for example, which sounds like a huge deal for pathing, highlighting and such. I can also link whatever gameobject is on top of it to the tile itself, so I could call something like tile[6, 2].ObjectOnTop.~WhateverInfoINeedFromIt, which also sounds super handy for overall logic.
But the shortcomings are also terrible - how do I even design and deploy different levels designs? The only way I can think of it is to figure out a way to do it all by hand, export that info somehow to a json file, and have the grid class that instantiates everything select which tile will be instantiated where based on the json info. I not only have no idea how to actually implement that, but I also think it would be an absurd amount of work for something that is supposed to be natural. I'm also not sure if a gameobject for each tile is a good idea in terms of performance. The biggest problem? It's easy to create such a grid if it's a simple squared tiles grid - but when we start talking about hexagons and isometric grids... it's not nearly as easy, honestly. The complex shapes make it so difficult to work with this kind of thing. For example, how do I even convert the mouse position into the equivalent tile? It's super easy for squares... not so much for the rest. It also kind of sucks that the grid is only really deployed when the game runs (is this generally considered a bad thing that I should avoid, btw?).
But don't worry, cause I've found the solution: tilemaps! Of course! It fixes all the problems I have, right? Supposedly yes, but it also removes all the power I had from having prefabs. Now I can't have any logic with tiles... They can't store any properties... so I'm doomed, I guess. I've read a bit on ways to overcome this (prefab brushes, custom classes inherenting from Tile, making a tilemap for each tile type), but they are honestly extremely niche and just don't feel right.
It's so weird, a generic grid system like this was supposed to be so simple and common. But I can barely find any information at all. It's like I'm missing this pretty obvious tool that no one seems to mention cause it's that obvious. So here I am, struggling to start a project cause I can't even figure out how to implement the basic structure of the game. Everything I see online leads me to tilemaps - but they only work for very basic stuff, from what I understood. I won't work for this kind of game, I think. I have no idea what to do at this point - there must be an optimal way to solve everything, the one that is likely used for all the devs that work on this kind of game. And honestly, there are a ton of them.
So, please, shed me some light. And thanks a lot in advance!
(Here's someone that posted an extremely similar question: Per Tilemap Tile Data Storage & Retrieval)
I have the exact same problem. The best i found is this: https://m.youtube.com/playlist?list=PLzDRvYVwl53uhO8yhqxcyjDImRjO9W722
It is playlist by CodeMonkey where he creates grid by script but also adding generics, which allow you to have that logic that you want and adding visual tiles. The only problem is that while I want squares while you want different shapes. I don't know how to do that, maybe you can adjust the grid(more likely tilemap it uses to display visuals) or maybe you should just let go of different shapes, i don't know.
Hope i helped at least little. I seen this post and it is very sad that noone replied to you. Hope you can achieve what you want and that it will be succes. Good luck and mainly have fun : )
convert mouse position to tile position can be done different ways, simplest would be to raycast the mouse and see if it hits a tile
probably easiest to make a 2dimensional array of tiles of class 'Tile', even if its hex break it down into a 2d array and offset , setup the tiles dynamically in code
for pathing and such djikstra algorithm is pretty useful
https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
May be it can help
grid = new gridSpace[roomWidth + 3, (roomWidth / 2) + 2];
int xStep = 4; # 2:1 isometry type
for (int x = 0; x < roomWidth - 1; x += xStep) #xStep depends by type of isometry
{
int minX = x;
int maxX = x + 2;
int localX = x;
for (int y = roomWidth / 2; y > -1; y--)
{
grid[localX, y] = gridSpace.empty;
if (localX == minX)
{
localX = maxX;
}
else
{
localX = minX;
}
}
}
Heey, i've been looking alot on Lidgren, and i've managed to get some simple console client and servers, but i'm having a really hard time with 2D...
Basically what i have so far is only Console based applications but i found an Example of a 2D game using Lidgren. You opened a server, and then two applications. They connected automatically and you could play with the two windows, seeing the character move in the other screen. That project used an array to load the textures and in the Draw() method it simple draws the array, but using a value from:
foreach (var kvp in positions)
{
// use player unique identifier to choose an image
int num = Math.Abs((int)kvp.Key) % textures.Length;`
// draw player
spriteBatch.Draw(textures[num], kvp.Value, Color.White);
}
Could someone explain what that num variable does? And if i wanted to use diffrent classes to do this, would i simply just do the same but in the player classes, and also, animations - how do you send texture update data?? Sorry that i'm asking so much..but i haven't found anything that actually helps :/
Thanks in advance and if you need to know something else, tell me! :)
The num variable simply chooses a unique texture, that will always be the same, from the textures array. Say you have 4 textures, but the Key the modulo operator (%) will get the remainder of 7/4, which would be 3. Basically it would wrap it around the amount of textures, because they would have to repeat (Ex, Id 4 and Id 8 have the same textures)
For now you can just use a static texture, but you can use the same code to choose a texture variation.
What do you mean texture update data? Such as changing textures, or updating positions? If changing textures, is the texture known or not? (Ex, can an ID/name be sent, or does the data have to?)
I'm working on some kind of mod for Terraria (written in C# and using XNA), in which I need to use some blend modes. I didn't have any troubles getting additive blending to work, but subtractive one causes me some problems.
I managed to display stuff with subtractive blending, but it doesn't really want to return to the standard mode. SpriteBatch.End and Begin doesn't help at all.
This is my custom BlendState:
public readonly static BlendState
bsSubtract = new BlendState{
ColorSourceBlend = Blend.SourceAlpha,
ColorDestinationBlend = Blend.One,
ColorBlendFunction = BlendFunction.ReverseSubtract,
AlphaSourceBlend = Blend.SourceAlpha,
AlphaDestinationBlend = Blend.One,
AlphaBlendFunction = BlendFunction.ReverseSubtract
},
Drawing code:
sb.End();
sb.Begin(SpriteSortMode.Immediate,bsSubtract);
(...drawing drawing blah...)
sb.End();
sb.Begin(SpriteSortMode.Immediate,BlendState.Additive);
The problem is, everything that is drawn after this code seems to still use some old options (half-transparent, bland). What am I doing wrong?
I even tried calling just sb.End() and sb.Begin() before setting the blend state back, or using another custom blend state which was a standard additive one, just with BlendFunctions set to Add, to no avail.
EDIT: Seems like setting ANY custom BlendState makes it do that...
EDIT2: Seems like the problem was me splitting the drawing to 3 separate places: one for item slots, one for tiles and one for world in general. And in one of these (items) I forgot to set the SpriteBatch before using and reset it afterwards. I should have spent more time looking at my code. Still, thanks for trying to help!
(can't close the question just yet, gonna close it after StackOverflow lets me do it)
The default blending mode is BlendState.AlphaBlend.
Try replacing BlendState.Additive with BlendState.AlphaBlend in your code. Or possibly NonPremultiplied, depending on what Terraria is actually using.
Better yet, you could read out exactly the blend state that Terraria was using, as SpriteBatch sets it on the graphics card and simply leaves it there. Here is some untested code that should do exactly that:
sb.End(); // Sets blend state
BlendState previousState = GraphicsDevice.BlendState; // Retrieve it
sb.Begin(SpriteSortMode.Immediate, bsSubtract);
// (...drawing drawing blah...)
sb.End();
sb.Begin(SpriteSortMode.Immediate, previousState); // Re-use it
Seems like the problem was me splitting the drawing to 3 separate places: one for item slots, one for tiles and one for world in general. And in one of these (items) I forgot to set the SpriteBatch before using and reset it afterwards. I should have spent more time looking at my code. Still, thanks for trying to help!