Unity2D: Using the left analogue stick to navigate through 2D space - c#

I am a beginner in Unity and I'm trying to make something pretty simple. However, I don't know where to start. I have a number of 'knots' in the scene, that the player will be able to select. They will then be able to connect two knots. I managed to find all knots in a range of 40 from the player's position and put them in an array. The next step would be to 'navigate' through the knots. I want the player to use the left analogue stick for that, but I don't know how to go about it. When they hold the stick at 120°, the knot closest to that position would be able to be selected by pressing another button. I looked at some UI navigation scripts, but this situation is pretty different as it's a two dimensional space. Does anyone have any suggestion on how to go about this? Thank you.
screenshot

It sounds to me like you're going to have to do some trigonometry to be able to find the nearest "knot." Each of these--at least if you're programming well--should each be an object whose x and y location variables can be accessed from your script.
You could iterate through the list of collected objects and compare them to your current location and store the object in a temporary variable if it is a shorter distance than the last object in the array.
Here's some pseudocode that should help illustrate my point:
for item in array {
Object closestKnotDist = Null
Float currentKnotDist = math.sqrt((player.x-item.x)**2 + (player.y-item.y)**2)
if currentKnotDist < closestKnotDist {
closestKnotDist = currentKnotDist
}
}
Thus, closestKnotDist will be the closest object to the player. Manipulate it how you will.
Not sure if this answered your question, but feel free to add some more explanation if not!

Related

Best way to implement a 2D hex-based/isometric grid system in Unity (for complex tiles)?

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;
}
}
}

Creating AI in c# to work through a simple game

I want to try and get an AI to find a sequence of moves that wins in Marble Solitaire. I've completed the system which moves a random cylinder and also the system which undoes the previous move. All I need to do now is to work out how and when the AI undoes moves. I had no idea what to do so I sort of randomly tried things, and I had enough so I decided to ask here.
Here's the code I think you need to help me solve it - feel free to ask me for more snippets, I don't just want to overload you with meaningless code:
private int index; Increases when a move has been tried my the AI, and said move didn't work. I use it to stop the program from looping over the same move without checking others.
Below is the current code I use to determine whether the AI should undo a move or not, but it doesn't seem to work as I want:
if (possibleMove.Count < index)
{
index = 0;
undoMove();
}
else if (possibleMove.Count == 0)
{
undoMove();
} //possibleMove is a list of all possible Moves the AI has found
The code snippet above activates at the very end of findMove()
The general format of the code goes like this:
private void findEmpty()
{
findMove();
}
private void findMove()
{
makeMove();
}
private void makeMove()
{
}
private void undoMove()
{
}
Rules of Marble Solitaire
The player makes successive capturing moves, removing a single piece each turn until is it impossible to make any more capturing moves.
Each turn, the player captures a piece by jumping over that piece in any direction (not diagonally) from two spaces away a vacant point, making sure that there is a piece you can jump over.
Therefore, the first turn can be made only by jumping a piece into the middle hole from one of 4 possible points.
Image of marble solitaire:
You can do this with the BFS method of graph searching. What you can do is find a way to represent the board, it can be an array of booleans to represent marbles or gaps or anything you can think of, so long as it's easy for you to understand and manipulate.
Then you would have a queue that so far only holds the initial state of the board. You then set your current state to the first state in the queue and then remove it from the queue. You can now use findMoves(currentState) to return a list of states that you can access from this current move. Add each of those states to the end of the queue, and then once again set your current state to the first state in the queue and remove it and use findMoves repeatedly until your current state matches some sort of goal state. In your particular problem you can just run this until findMoves(currentState) returns an empty array since that would mean there are no more moves for you to be able to do.
That would get you to a solution, however it wouldn't keep track of the path for you. You can keep track of the path itself in any number of ways, for example instead of adding just the next state to the queue you can add an array of all of the states so far in that path and just use the last value when calculating the next states you can go to. But that's just an example.

How to calculate the numbers from different gameObjects together in Unity c#

I'm building a Unity game where you have feelers, and by clicking the color given at that moment, you can get or lose a score, time or you get a game over screen.
My problem is - I have a lot gameObjects and each one calculates scores alone, (eache one have his own score int) and I need one code detects all scores number one, so I can see the scores one point (about how to see it, this is less important).
The name of the number that I want to find is called (how creative): score.
And yes, this is a public float.
I am most glad if I could write this document duration (unless you have no choice anyway ...)
sorry about any grammar mistakes, I do my best.
Thanks from advance
Roei Meiri.
:)
I can't image this would be very efficient, you would probably get better performance if you keep you own list of all the scoring objects(add to the list when creating the scoring object).
That being said...(uncompiled example).
Assuming you want to find of all objects with a particular component, like
class ScoringObject:Monobehavior
then you can find them all and add up the scores like so...
float totalscore=0;
ScoringObject[] listOfScores= Object.FindObjectsOfType(typeof(ScoringObject)) as ScoringObject[];
foreach (ScoringObject scorObject in listOfScores) {
totalscore+=listOfScores.score;}
http://docs.unity3d.com/ScriptReference/Object.FindObjectsOfType.html

How do I make a class stored in a 2d-array "aware" of their position in it?

I think the title says it all... but for completeness sake here is the full problem.
The Problem
So, I have a 2-column array (a matrix, or "grid") in Visual Basic/C#/Anything.net comprised of Cell instances declared as Public Matrix(,) As Cell.
A Cell is roughly this:
Class Cell
Public Value as integer
Public Height as integer
Public Tags as Dictionary
Sub New(Optional v As CellType = CellType.Void)
value = v
type = v
End Sub
Function GetPos() as Point
*need arcane necromancy here*
End Sub
End Class
The question is simple, but I know the answer may not: can I get the Cell's position without passing it in the constructor?
Here is an example of what I'd like to achieve (always given Public Matrix(,) As Cell):
Dim x,y as integer
Dim apple as Cell = GetARandomAppleFrom(Matrix)
x=apple.GetArrayPos.x
y=apple.GetArrayPos.y
Console.WriteLine(String.Format("An Apple is in {0}, {1}",x,y)
A side question about the need of this question
At the moment I am using the following snippet of code to initialize all of the cells to a zero-value because using Matrix.Initialize() failed miserably leaving every element set to nothing.
If the methods description says it calls the default constructor, then why did it fail?
Although I doubt my initialization is correct from a coding/efficiency perspective, as I think that a double loop isn't that great...
For x = 0 To Me.zWidth
For y = 0 To Me.zHeight
Matrix.SetValue(New Cell(CellTypes.Void), x, y)
Next
Next
I am sticking to it for now. Hence here is a
Possible Solution
This implies that I could pass the indices to a Position field at initialization time - through the constructor - like this...
For x = 0 To Me.zWidth
For y = 0 To Me.zHeight
Matrix.SetValue(New Cell(CellTypes.Void,x,y), x, y)
Next
Next
But, since a Cell could change position or be overwritten, I would like its position to be dynamically determined.
However, if nothing better comes in the radar I will definitely use this approach and then update the value as per position changes,
Addendums
Some info that may - or not - be useful:
The Matrix size is less or equal to (512,512)
This is going to become a terrain data-map generator for an isometric (so no 3d, but I already have an height variable in cells) game with fairly small maps, with support to superficial features like mountains, river(s),
Why can't you just cut down your random picker to just return the x,y value found and use that to retrive your cell? Something like this:
Dim pt as Point
pt = GetRandomPosition()
Dim apple as Cell = Matrix(pt.X,pt.Y)
Console.WriteLine(String.Format("An Apple is in {0}, {1}",pt.X,pt.Y)
First off to initialize N elements you must call your initializer N times, no efficiency problem there.
To answer your question: Your item shouldn't care about its position. The position of an item in a collection is not a problem of the item itself and can lead to headaches very quickly if you move your item or change the collection.
What if your collection changes from a 2d matrix to a 3d one? You have to rewrite code and add a Z variable (and that just a quick example).
I'd try to structure my code/solution completely in another way.
By the way, a item can locate itself inside a collection by looking for a reference to itself. (Adapt code to your matrix as needed)
GetPosition( Array source)
{
foreach(var element in source)
Object.ReferenceEquals(this,element)
}
Performance are bad since you loop the collection but it may fit your needs
It really is a question of modelling. I personally would prefer if cells knew about their position since it seems to be important to them, but for one you appear to dislike this approach, and for two, when updating positions this has to be done (by a helper method) in two realms at once - in the affected cells and in the grid, which can be problematic. Thus, something else:
How about stepping away from a simple 2D array towards building your own type like a somewhat smarter array which not only keeps the grid of cells as a simple 2D array, but also takes record of each Cell with their coordinates -- a dictionary which maps each contained Cell to a pair of ints representing the x and y. Let's call that smart array SmartArray. It would need methods for moving cells around, which update the map and the grid atomically (which is OK because all the changes are within the SmartArray "realm"). Then you can ask the SmartArray instance "Where on the grid is Cell c?" and you'll have an answer in O(1). That'd be a tradeoff towards speed over memory footprint. Each Cell must, however, know about their containing SmartArray so it knows who to ask.
You can also leave out the map and keep the query methods, but make them traverse the grid each time a question is asked. The answer will be the same, lookups will take O(n^2), but moving cells will be easier because you only have to update one structure. That'll turn around the tradeoff towards one favoring memory footprint over speed, and it is essentially the Double Loop you mentioned in the q.

C# Lidgren - Send positions and playerstates?

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?)

Categories