Unity3D Changing texture at runtime not working on Android build - c#

I'm working on a digital book for an Android tablet on Unity 5. I'm using this Page Curl plugin from the Asset Store.
I have 3 main planes: LeftPage, RightPage and TurningPage, and I keep an index of which page I'm looking for each one of this pages so I can manage the corresponding textures. When I click on one of the Left or Right pages, the turning page animation starts playing and when it ends, I update the index values and the corresponding textures.
It works perfect in Unity Editor and perfect with Unity Remote in the tablet, but when I run the installed apk, the turning page is always showing the textures assigned at the begining. The Left and Right pages work fine.
Printing the assigned texture name (pageFront.mainTexture.name) I get the correct texture which is equivalent to the page index value, but the turningPage keeps showing the initial (indPage = 0) texture.
All the textures are asigned on the editor on a Texture2D array.
void Update()
{
...
// If click is in one of four defined areas.
if (mouseX > 970 && mouseX < 1024 && canFlipFwd)
{
if (mouseY > 250 && mouseY < 710)
{
clickCase = 1; // Play animation 1.
changePageFwd();
}
else if (mouseY > 50 && mouseY <= 250)
{
clickCase = 2; // Play animation 2.
changePageFwd();
}
}
else
{
...
}
}
void PageFlipOver(bool pageTurned)
{
if (pageTurned)
{
// Update page index.
indRight += 2;
indPage += 2;
if (indLeft + 2 < pages.Length)
{
indLeft += 2;
leftBackground.mainTexture = pages[indLeft];
if (indLeft + 2 < pages.Length)
pageBack.mainTexture = pages[indLeft + 2];
else
pageBack.mainTexture = pages[indLeft];
}
if (!canFlipBkw)
canFlipBkw = true;
}
canFlip = true;
}
void changePageFwd()
{
if (indRight < pages.Length)
{
rightBackground.mainTexture = pages[indRight];
}
else
{
rightBackground.mainTexture = alpha;
canFlipFwd = false;
}
if (indPage < pages.Length)
pageFront.mainTexture = pages[indPage];
}
Any help is welcome, I've been stuck with this for two weaks and I can't find whats wrong.

Related

Slow update time with tiles and MouseState MonoGame

Very new developer here.
In my program I have a randomly generating world map using a simplex noise library. On top of this I am attempting to draw a tilemap of transparent 4x4 tiles that appear slightly translucent when the mouse is hovering over one.
I've got this working but it takes about 3 whole seconds for the highlighted tile to update to the mouse's current position. Is there anything I could do to solve this?
This is my code for the MouseState check in the tile class:
public override void Update(GameTime gameTime)
{
_previousMouse = _currentMouse;
_currentMouse = Mouse.GetState();
var mouseRectangle = new Rectangle(_currentMouse.X, _currentMouse.Y, 1, 1);
_isHovering = false;
if (mouseRectangle.Intersects(Rectangle))
{
_isHovering = true;
if (_currentMouse.LeftButton == ButtonState.Released && _previousMouse.LeftButton == ButtonState.Pressed)
{
Click?.Invoke(this, new EventArgs());
}
}
}
Sorry if this is formatted wrong or badly asked, first post so still getting to grips with everything :)
Invert the logic:
Instead of checking thousands of tile objects against the mouse, apply the mouse to a single object.
Assuming you have a list or array of tile objects:
Add a new object to check for mouse hover and click:
public class MouseDetect(Tile[] tiles) // replace with List<> as needed
{
int PrevHover = -1; // used to unHover
// if (Area == Screen) make the next two lines `const`, so the compiler will remove all uses...
int AreaX = 0; //Area x offset
int AreaY = 0; //Area y offset
int AreaW = 800; //Area width
int AreaH = 480; //Area height
const int Grid = 4; // assumes square
const int GridW = AreaW / Grid;
// I Will assume the `Delegate Click` in `Tile` is public
public void Update(MouseState ms, MouseState oms), //_currentMouse = ms and _previousMouse = oms;
{
int mouseIndex = (ms.X - AreaX) % Gridw + (ms.Y - AreaY) / GridW;
tiles[PrevHover].Hover = false;
PrevHover = mouseIndex;
tiles[PrevHover].Hover = true;
//Check Release
if(tiles[PrevHover].Hover && ms.LeftButton == ms.ButtonState.Released && oms.LeftButton == ButtonState.Pressed)
tiles[PrevHover].Click(tiles[PrevHover], new EventArgs());
}
}
Remove the Update from the Tile class.
Notes for anyone reading this later:
Never call Mouse.GetState(); more than once per step.
Predefined or framework names such as Rectangle should never be used as an identifier.
i.e renamed and corrected to CollRectangle
if (CollRectangle.Contains(ms.Position))

Transition from one path-finding grid to another

for some context, I'm creating a simple game for a university project where there are multiple seperate "islands" that the player can walk to.
The player also has a dog companion that is using an A* pathfinding algorithm that randomly selects an area within a certain range of the player, checks if they can walk there and it's not too close to where the dog already is, and returns true or not.
The issue I'm coming across is whilst the code works somewhat perfectly on the first island, when transitioning to the second island, it appears that every path that the dog tries to take gets rejected and causes a stack overflow error.
I've had a look at the debug inspector within unity to make sure that the scripts are referencing the scripts that they depend on rather than the first islands scripts, but it all appears to be correct.
I'm hoping to get some fresh eyes on this as it's only been me working on this for a few days now.
The code the error is getting created on:
public Node NodeFromWorldPoint(Vector3 worldPosition)
{
float percentX = (worldPosition.x - transform.position.x) / gridWorldSize.x + 0.5f - (nodeRadius / gridWorldSize.x);
float percentY = (worldPosition.z - transform.position.z) / gridWorldSize.y + 0.5f - (nodeRadius / gridWorldSize.y);
percentX = Mathf.Clamp01(percentX);
percentY = Mathf.Clamp01(percentY);
int x = Mathf.FloorToInt(Mathf.Min(gridSizeX * percentX, gridSizeX-1));
int y = Mathf.FloorToInt(Mathf.Min(gridSizeY * percentY, gridSizeY - 1));
return grid[x, y];
}
This is the code that generates a random location within a range and returns if it's valid or not:
public Vector3 GetRandomPointInBounds(Bounds bounds)
{
desintationReached = false;
Vector2 location;
location = new Vector2(
Random.Range(bounds.min.x, bounds.max.x),
Random.Range(bounds.min.y, bounds.max.y)
);
if (CheckIfPointInCollider(location))
{
//Debug.DrawLine(transform.position, location,Color.green,20f);
return new Vector3(location.x, location.y, 0);
}
else
{
Debug.DrawLine(transform.position, location, Color.red, 0.1f);
//Debug.Log("Invalid Location:" + location);
return GetRandomPointInBounds(bounds);
}
}
public bool CheckIfPointInCollider(Vector2 location)
{
Node targetNode = grid.NodeFromWorldPoint(new Vector3(location.x, location.y, 0));
if (targetNode.walkable && !rangeToIgnore.OverlapPoint(location))
{
return true;
}
else
{
return false;
}
}
Heres the code that transitions between the first grid object and the second:
public void Launch()
{
// Increasing Current Island Count
gm.IncreaseIsland();
Debug.Log("Transitioning to island: " + gm.GetCurrentIsland());
// Enabling & Disabling Monty, Player, Canoe Single and their depencies
canoeAIO.transform.position = canoeSpawnPoints[0].transform.GetChild(currentIsland).transform.position;
canoeAIO.SetActive(true);
canoeAIO.GetComponent<CanoePaddle>().beached = false;
canoeAIO.GetComponent<CanoePaddle>().canPaddle = true;
canoe.SetActive(false);
player.SetActive(false);
monty.SetActive(false);
layerManager.SetActive(false);
interactionsManager.SetActive(false);
pathwayCollider.SetActive(false);
spritesManager.SetActive(true);
//Setting all other pathfinding managers to inactive
for (int i = 0; i < pathfindingManagers.Length; i++)
{
pathfindingManagers[i].SetActive(false);
}
// Activating the next islands pathfinding and clearing any existing path requests
pathfindingManagers[gm.GetCurrentIsland()].SetActive(true);
PathRequestManager.ClearRequests();
monty.GetComponent<MontyStateActions>().StopAllCoroutines();
montyStateVariables.grid = pathfindingManagers[gm.GetCurrentIsland()].GetComponent<MyGrid>();
montyStateVariables.currentlyOnPath = false;
//hide monty
//hide canoe object
//show canoe all in one at the new location
cameraHandler.SwitchToCanoe();
}
(btw, Monty is the name of the dog :) )
I hope this is helpful, and if there is any more code/images you need I'll try and get them uploaded

2D parallaxing background on both X and Y axis using XNA and C#

I am working on a space shooter game using XNA and have followed multiple tutorials to create a parallax background. So far I can get it to go along one axis, either X or Y, but not both at the same time. I have a camera class that follows the player, which the player moves (instead of the 'world'), since I figured it would be easier to just move the player versus moving everything else around the player.
So far, the background doesn't keep up with the player, and it also can't comprehend both axis at the same time. I thought about a tile engine, but that wouldn't let me parallax different layers would it?
Could anyone help me understand what I need to do, or recommend a tutorial that can do both axis at the same time? I can't seem to find the answer on my own this time.
Here is the code for my background class:
class Background
{
// Textures to hold the two background images
Texture2D spaceBackground, starsParallax;
int backgroundWidth = 2048;
int backgroundHeight = 2048;
int parallaxWidth = 2048;
int parallaxHeight = 2048;
int backgroundWidthOffset;
int backgroundHeightOffset;
int parallaxWidthOffset;
int parallaxHeightOffset;
public int BackgroundWidthOffset
{
get { return backgroundWidthOffset; }
set
{
backgroundWidthOffset = value;
if (backgroundWidthOffset < 0)
{
backgroundWidthOffset += backgroundWidth;
}
if (backgroundWidthOffset > backgroundWidth)
{
backgroundWidthOffset -= backgroundWidth;
}
}
}
public int BackgroundHeightOffset
{
get { return backgroundHeightOffset; }
set
{
backgroundHeightOffset = value;
if (backgroundHeightOffset < 0)
{
backgroundHeightOffset += backgroundHeight;
}
if (backgroundHeightOffset > backgroundHeight)
{
backgroundHeightOffset -= backgroundHeight;
}
}
}
public int ParallaxWidthOffset
{
get { return parallaxWidthOffset; }
set
{
parallaxWidthOffset = value;
if (parallaxWidthOffset < 0)
{
parallaxWidthOffset += parallaxWidth;
}
if (parallaxWidthOffset > parallaxWidth)
{
parallaxWidthOffset -= parallaxWidth;
}
}
}
public int ParallaxHeightOffset
{
get { return parallaxHeightOffset; }
set
{
parallaxHeightOffset = value;
if (parallaxHeightOffset < 0)
{
parallaxHeightOffset += parallaxHeight;
}
if (parallaxHeightOffset > parallaxHeight)
{
parallaxHeightOffset -= parallaxHeight;
}
}
}
// Constructor when passed a Content Manager and two strings
public Background(ContentManager content,
string sBackground, string sParallax)
{
spaceBackground = content.Load<Texture2D>(sBackground);
backgroundWidth = spaceBackground.Width;
backgroundHeight = spaceBackground.Height;
starsParallax = content.Load<Texture2D>(sParallax);
parallaxWidth = starsParallax.Width;
parallaxHeight = starsParallax.Height;
}
public void Draw(SpriteBatch spriteBatch)
{
// Draw the background panel, offset by the player's location
spriteBatch.Draw(
spaceBackground,
new Rectangle(-1 * backgroundWidthOffset,
-1 * backgroundHeightOffset,
backgroundWidth,
backgroundHeight),
Color.White);
// If the right edge of the background panel will end
// within the bounds of the display, draw a second copy
// of the background at that location.
if (backgroundWidthOffset > backgroundWidth)
{
spriteBatch.Draw(
spaceBackground,
new Rectangle(
(-1 * backgroundWidthOffset) + backgroundWidth, 0,
backgroundWidth, backgroundHeight),
Color.White);
}
else //(backgroundHeightOffset > backgroundHeight - viewportHeight)
{
spriteBatch.Draw(
spaceBackground,
new Rectangle(
0, (-1 * backgroundHeightOffset) + backgroundHeight,
backgroundHeight, backgroundHeight),
Color.White);
}
// Draw the parallax star field
spriteBatch.Draw(
starsParallax,
new Rectangle(-1 * parallaxWidthOffset,
0, parallaxWidth,
parallaxHeight),
Color.SlateGray);
// if the player is past the point where the star
// field will end on the active screen we need
// to draw a second copy of it to cover the
// remaining screen area.
if (parallaxWidthOffset > parallaxWidth)
{
spriteBatch.Draw(
starsParallax,
new Rectangle(
(-1 * parallaxWidthOffset) + parallaxWidth,
0,
parallaxWidth,
parallaxHeight),
Color.White);
}
}
}
The main game then has ties to move the backgrounds, along with the player.
background.BackgroundWidthOffset -= 2;
background.ParallaxWidthOffset -= 1;
Visually, the background is sort of jumpy, and seems to randomly skip or overlap background tiles.
I've used this method in the past with great results:
http://www.david-gouveia.com/scrolling-textures-with-zoom-and-rotation/
It uses a shader to accomplish the effect, resulting in a fast implementation.
There is a complete example here.

How to make monster move left then right continuously C# XNA

i'm making my first game on XNA for my class. I'm trying to make the monsters move left and right automatically. I have total 4 monsters for now. I'm trying to get them move left then right within the screen.
//Monster movements
for (int i = 0; i < numOfMonster; i++)
{
if (destinationMonster[i].X >= screenWidth - 60)
{
while(destinationMonster[i].X != -10)
moveLeft = true;
}
else
{
moveRight = true;
}
if (moveLeft)
{
int temp = destinationMonster[i].X;
temp = destinationMonster[i].X - monsterSpeed;
//This prevents the object passing the screen boundary
if (!(temp < -10))
{
destinationMonster[i].X = temp;
}
moveLeft = false;
}
if (moveRight)
{
int temp = destinationMonster[i].X;
temp = destinationMonster[i].X + monsterSpeed;
//This prevents the object passing the screen boundary
if (!(temp > screenWidth - 50))
{
destinationMonster[i].X = temp;
}
moveRight = false;
}
}
Your first problem is your while statement, once you enter it you are not going to exit because you are not changing your X value. If it were me I would have a bool array variable corresponding to each of your monsters. I would also change your conditional to trigger the change of the boolean value once the monster has reached the extents at either end. Something like this.
if (destinationMonster[i].X >= screenWidth - 60)
{
moveRight[i] = false ;
}
else if (destinationMonster[i].X <= -10)
{
moveRight[i] = true ;
}

SpriteSheet Animation with XNA

I'm working on my First 2D Game with XNA and I have a little problem.
To give a running effect to my Sprite, I scroll through a SpriteSheet with this code(running right):
if (AnimationDelay == 6)
{
if (CurrentFrameR.X < SheetSizeR.X)
{
++CurrentFrameR.X;
}
else
{
CurrentFrameR.Y++;
CurrentFrameR.X = 1;
}
if (CurrentFrameR.Y >= SheetSizeR.Y)
{
CurrentFrameR.X = 0;
CurrentFrameR.Y = 0;
}
AnimationDelay = 0;
}
else
{
AnimationDelay += 1;
}
xPosition += xDeplacement;
}
And these are the objects used :
Point FrameSizeR = new Point(29, 33);
Point SheetSizeR = new Point(5, 1);
Point CurrentFrameR = new Point(0, 0);
int AnimationDelay = 0;
I have the same Code with different SpriteSheet when the sprite is running Left.
Everything is working fine I'd say 90% of the time but the other 10% the sprite animation stays on one Frame of the SpriteSheet, on both directions(left and right) and it stays stuck until I close the program.
The thing is I can't quite figure out why since it never happens at the same moment..Sometimes after 10,15,30 seconds and sometimes even on boot!
Any idea why?
Thanks in advance and let me know if you need any other parts of the code
Your code can be rewrited this way:
ElapsedTimeFrame += (float) GameTime.ElapsedTime.TotalSeconds;
if (ElapsedTimeFrame >= TimePerFrame)
{
CurrentFrameR.X = (CurrentFrameR.X + 1) % SheetSizeR.X;
if (CurrentFrameR.X == 0)
{
CurrentFrameR.Y = (CurrentFrameR.Y + 1) % SheetSizeR.Y;
}
ElapsedTimeFrame-= TimePerFrame;
}
But you have to show more code to guess what happens...

Categories