I trying to slice Sprite(type casted to Texture2D) by script,
when project is running on Android or IOS Platform
is it possible by script??
I trying to use UnityEditor Class and it is work on Computer
but When I trying to Build Android or IOS It is failed.
void OnPreprocessTexture()
{
TextureImporter textureImporter = (TextureImporter)assetImporter;
textureImporter.textureType = TextureImporterType.Sprite;
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
textureImporter.mipmapEnabled = false;
textureImporter.filterMode = FilterMode.Point;
}
public void OnPostprocessTexture(Texture2D texture)
{
Debug.Log("Texture2D: (" + texture.width + "x" + texture.height + ")");
int spriteSize = 350;
int colCount = texture.width / spriteSize;
int rowCount = texture.height / spriteSize;
List<SpriteMetaData> metas = new List<SpriteMetaData>();
for (int r = 0; r < rowCount; ++r)
{
for (int c = 0; c < colCount; ++c)
{
SpriteMetaData meta = new SpriteMetaData();
meta.rect = new Rect(c * spriteSize, r * spriteSize, spriteSize, spriteSize);
meta.name = c + "-" + r;
metas.Add(meta);
}
}
TextureImporter textureImporter = (TextureImporter)assetImporter;
textureImporter.spritesheet = metas.ToArray();
}
public void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
{
Debug.Log("Sprites: " + sprites.Length);
}
It is not working When running project on Android or IOS
[What I want]
Procedure
During running on Android or IOS Platform
1) Receive some Images from server (Url or file)
2) Load Image on C# script
3) Change type Images to Texture or Sprite ect...
4) Slice Images(Don't use Editor)
5) Save Pieces of Image
6) Use piece of Image
What I want is all procedure worked by Script
TextureImporter belongs to the UnityEditor namespace which doesn't exist in a built app but only within the Unity Editor itself. → You can not use this!
What you can do is using Sprite.Create to generate a sprite from a given Texture2D.
Cropping
If it is actually only about cutting out a certain part of the texture to use it as sprite than you only need to define in the rect parameter the part of the texture you want to use from that image.
// Wherever you get the texture from
Texture texture = ...;
// E.g. for using the center of the image
// but half of the size
var rect = new Rect(texture.width / 4, texture.height / 4, texture.width / 2, texture.height / 2);
// Create the sprite
var sprite = Sprite.Create(texture, rect, Vector2.one * 0.5f);
where rect is the
Location of the Sprite on the original Texture, specified in pixels.
Slicing
If you additionally want a slicing border (which you usually define in the Sprite Editor within Unity) there is an overload of Sprite.Create that additionally takes a border parameter e.g.
var borders = new Vector4(2, 2, 2, 2);
var sprite = Sprite.Create(texture, rect, Vector2.one * 0.5f, 100, SpriteMeshType.FullRect, borders);
where border
Returns the border sizes of the sprite.
X=left, Y=bottom, Z=right, W=top.
API doesn't say it but I guess like the rect values those values are also in pixels.
I solved using rect and Sprite Rnederer
here is my code
void Start()
{
rect = new Rect(0f, 0f, 255, 255);
this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(img, rect, new Vector2(0.5f, 0.5f));
this.GetComponent<RectTransform>().localScale = new Vector3(100, 100, 0);
StartCoroutine(Update());
}
/*
* rect = new Rect(i, 0, 255, 255);
this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(img, rect, new Vector2(0.5f, 0.5f));*/
IEnumerator Update()
{
while (true)
{
if (i < 1000)
{
i += 255;
if (i > 770)
{
i = 0;
}
}
yield return new WaitForSeconds(0.25f);
rect = new Rect(i, 0f, 255, 255);
this.GetComponent<SpriteRenderer>().sprite = Sprite.Create(img, rect, new Vector2(0.5f, 0.5f));
}
}
Related
I have a 32x32 sprite that I am trying to access the pixel data of and modify.
To do this I am simply taking the sprite's texture, creating a new texture based on the old and then changing the pixel values of the new texture. I then create a new sprite with the modified texture and change the SpriteRenderer's sprite parameter to the new sprite.
However, when I actually run my script what I get is a huge grey square, easily 10x the size of the original 32x32 sprite. I'm very new to unity so I'm not sure why this is happening. Any insight would be great.
private Sprite sprite;
private Texture2D texture;
// Use this for initialization
void Start ()
{
sprite = this.gameObject.GetComponent<SpriteRenderer>().sprite;
texture = sprite.texture;
Texture2D newTexture = modifyTexture(texture);
SpriteRenderer sr = this.gameObject.GetComponent<SpriteRenderer>();
sr.sprite = Sprite.Create(newTexture, new Rect(0, 0, newTexture.width, newTexture.height), new Vector2(0, 0), 10);
}
public Texture2D modifyTexture(Texture2D baseTexture)
{
Texture2D newTexture = new Texture2D(baseTexture.width, baseTexture.height);
int x = 0;
while(x < newTexture.width)
{
int y = 0;
while(y < newTexture.height)
{
Color currentPixel = baseTexture.GetPixel(x,y);
Color modifiedPixel = currentPixel;
modifiedPixel.r = (float)(modifiedPixel.r + 0.10);
modifiedPixel.b = (float)(modifiedPixel.b + 0.10);
modifiedPixel.g = (float)(0.10);
newTexture.SetPixel(x, y, modifiedPixel);
y++;
}
x++;
}
Debug.Log(newTexture.GetPixel(5, 5).ToString());
return newTexture;
}
After modifying pixels of a Texture, you must call the Apply function upload the modified pixels to the graphics card.
public Texture2D modifyTexture(Texture2D baseTexture)
{
Texture2D newTexture = new Texture2D(baseTexture.width, baseTexture.height);
int x = 0;
while (x < newTexture.width)
{
int y = 0;
while (y < newTexture.height)
{
Color currentPixel = baseTexture.GetPixel(x, y);
Color modifiedPixel = currentPixel;
modifiedPixel.r = (float)(modifiedPixel.r + 0.10);
modifiedPixel.b = (float)(modifiedPixel.b + 0.10);
modifiedPixel.g = (float)(0.10);
newTexture.SetPixel(x, y, modifiedPixel);
y++;
}
x++;
}
//Upload changes to Graphics graphics card
newTexture.Apply();
Debug.Log(newTexture.GetPixel(5, 5).ToString());
return newTexture;
}
I have been trying to make my first ever game engine (in OpenTK and Im stuck. I am trying to incoperate animations and I'm trying to use sprite sheets because they would greatly decrease filesize.
I know that I need to use a for loop to draw all the sprites in sequence, but I dont have a clue about what I should do to make it work with spritesheets.
Here is my current drawing code:
//The Basis fuction for all drawing done in the application
public static void Draw (Texture2D texture, Vector2 position, Vector2 scale, Color color, Vector2 origin, RectangleF? SourceRec = null)
{
Vector2[] vertices = new Vector2[4]
{
new Vector2(0, 0),
new Vector2(1, 0),
new Vector2(1, 1),
new Vector2(0, 1),
};
GL.BindTexture(TextureTarget.Texture2D, texture.ID);
//Beginning to draw on the screen
GL.Begin(PrimitiveType.Quads);
GL.Color3(color);
for (int i = 0; i < 4; i++)
{
GL.TexCoord2((SourceRec.Value.Left + vertices[i].X * SourceRec.Value.Width) / texture.Width, (SourceRec.Value.Left + vertices[i].Y * SourceRec.Value.Height) / texture.Height);
vertices[i].X *= texture.Width;
vertices[i].Y *= texture.Height;
vertices[i] -= origin;
vertices[i] *= scale;
vertices[i] += position;
GL.Vertex2(vertices[i]);
}
GL.End();
}
public static void Begin(int screenWidth, int screenHeight)
{
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
GL.Ortho(-screenWidth / 2, screenWidth / 2, screenHeight / 2, -screenHeight / 2, 0f, 1f);
}
Thanks in advance!!! :)
Firstly, I beg you, abandon the fixed function pipeline. It blinds you and restricts your understanding and creativity. Move to core 3.1+, it's structural perfection is matched only by it's potentiality, and the collaborative forethought and innovation will truly move you.
Now, you'll want to store your sprite sheet images as a Texture2DArray. It took me some time to figure out how to load these correctly:
public SpriteSheet(string filename, int spriteWidth, int spriteHeight)
{
// Assign ID and get name
this.textureID = GL.GenTexture();
this.spriteSheetName = Path.GetFileNameWithoutExtension(filename);
// Bind the Texture Array and set appropriate parameters
GL.BindTexture(TextureTarget.Texture2DArray, textureID);
GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2DArray, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
// Load the image file
Bitmap image = new Bitmap(#"Tiles/" + filename);
BitmapData data = image.LockBits(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
// Determine columns and rows
int spriteSheetwidth = image.Width;
int spriteSheetheight = image.Height;
int columns = spriteSheetwidth / spriteWidth;
int rows = spriteSheetheight / spriteHeight;
// Allocate storage
GL.TexStorage3D(TextureTarget3d.Texture2DArray, 1, SizedInternalFormat.Rgba8, spriteWidth, spriteHeight, rows * columns);
// Split the loaded image into individual Texture2D slices
GL.PixelStore(PixelStoreParameter.UnpackRowLength, spriteSheetwidth);
for (int i = 0; i < columns * rows; i++)
{
GL.TexSubImage3D(TextureTarget.Texture2DArray,
0, 0, 0, i, spriteWidth, spriteHeight, 1,
OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte,
data.Scan0 + (spriteWidth * 4 * (i % columns)) + (spriteSheetwidth * 4 * spriteHeight * (i / columns))); // 4 bytes in an Bgra value.
}
image.UnlockBits(data);
}
Then you can simply draw a quad, and the Z texture co-ordinate is the Texture2D index in the Texture2DArray. Note frag_texcoord is of type vec3.
#version 330 core
in vec3 frag_texcoord;
out vec4 outColor;
uniform sampler2DArray tex;
void main()
{
outColor = texture(tex, vec3(frag_texcoord));
}
I need to draw a terrain and have a camera with surfacefollow in XNA, but in some places it doesnt draw what is suposed to draw and draws the terrain behind it. Any suggestions of what it may be?
public void Draw()
{
camera.Effect.TextureEnabled = true;
camera.Effect.VertexColorEnabled = false;
camera.Effect.World = worldMatrix;
camera.Effect.Texture = texture;
camera.Effect.CurrentTechnique.Passes[0].Apply();
device.SetVertexBuffer(vertexBuffer);
device.Indices = indexBuffer;
for (int i = 1; i < (alturas.Height - 1); i++)
{
device.DrawIndexedPrimitives(PrimitiveType.TriangleStrip, 0, 0, heights.Width * 2, (heights.Width * 2) * i, (heights.Width * 2) - 2);
}
}
heights is the texture of the height map. The construction of the vertices is working fine.
i am trying to crop a texture2d in xna. i have found the following code which will crop the image on the top and right sides, i have played around with the code and cannot figure a way to crop all sides at a specific interval. below is the code i have been trying to modify:
any help or ideas would be much appreciated.
Rectangle area = new Rectangle(0, 0, 580, 480);
Texture2D cropped = new Texture2D(heightMap1.GraphicsDevice, area.Width, area.Height);
Color[] data = new Color[heightMap1.Width * heightMap1.Height];
Color[] cropData = new Color[cropped.Width * cropped.Height];
heightMap1.GetData(data);
int index = 0;
for (int y = 0; y < area.Y + area.Height; y++) // for each row
{
for (int x = 0; x < area.X + area.Width; x++) // for each column
{
cropData[index] = data[x + (y * heightMap1.Width)];
index++;
}
}
cropped.SetData(cropData);
Here is the code to crop a texture. Note that the GetData method can already select rectangular subsection of the image - there is no need to manually crop.
// Get your texture
Texture2D texture = Content.Load<Texture2D>("myTexture");
// Calculate the cropped boundary
Rectangle newBounds = texture.Bounds;
const int resizeBy = 20;
newBounds.X += resizeBy;
newBounds.Y += resizeBy;
newBounds.Width -= resizeBy * 2;
newBounds.Height -= resizeBy * 2;
// Create a new texture of the desired size
Texture2D croppedTexture = new Texture2D(GraphicsDevice, newBounds.Width, newBounds.Height);
// Copy the data from the cropped region into a buffer, then into the new texture
Color[] data = new Color[newBounds.Width * newBounds.Height];
texture.GetData(0, newBounds, data, 0, newBounds.Width * newBounds.Height);
croppedTexture.SetData(data);
Of course, keep in mind that SpriteBatch.Draw can take a sourceRectangle parameter, so you may not even need to copy the texture data around at all! Just use a subsection of the original texture. For example:
spriteBatch.Draw(texture, Vector2.Zero, newBounds, Color.White);
(Where newBounds is calculated in the same way as in the first code listing.)
I'm currently working on a Windows Phone game similar to Tiny Wings and I've been having trouble with collision detection between the player's character and the hills. I've been looking into a few different ways to do this including the Farseer Physics engine and a Silverlight tutorial
Player's character initialization
lander = new Lander(new Vector2(graphics.PreferredBackBufferWidth / 4, 100));
LoadContent
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
primitiveBatch = new PrimitiveBatch(GraphicsDevice);
// Load textures
landerTexture = this.Content.Load<Texture2D>(".\\Sprites\\boysmall");
// Initialize lander based on texture
lander.Width = landerTexture.Width;
lander.Height = landerTexture.Height;
// Load the parallaxing background
bgLayer1.Initialize(Content, "hillsbackground", GraphicsDevice.Viewport.Width, -2, 150);
bgLayer2.Initialize(Content, "hillsbackground2", GraphicsDevice.Viewport.Width, -3, 220);
// Load hills
string[] hillsArray = new string[2]{"textured","hillsmooth"};
mainHill.Initialize(Content, hillsArray, GraphicsDevice.Viewport.Width, -4);
// Load Sky
mainBackground.Initialize(Content, "mainbackground", GraphicsDevice.Viewport.Width, -1, 0);
}
I understand that fundamentally, collision detection looks for intersection points between two rectangles, and have done that for the "lander", but don't know how I can do it for the hills and how to make it slide down smoothly? let me know if you need any additional code, thanks for your help!
Rectangle attempt for Lander
public Rectangle GetScreenRectangle()
{
// calculate the rectangle from the current location
// and the current source rectangle
var rectangle = new Rectangle(
(int)graphics.PreferredBackBufferWidth / 4,
(int)100,
lander.Width,
lander.Height);
return rectangle;
}
Hills Code
class MainHill
{
// The image representing the parallaxing background
Texture2D texture;
// An array of positions of the parallaxing background
//Vector2[] positions;
// The speed which the background is moving
int speed;
// Object array holding position and texture of each live texture
object[,] positionsArray = new object[2, 2];
public void Initialize(ContentManager content, Array hillsArray, int screenWidth, int speed)
{
// Load the background texture we will be using
//texture = content.Load<Texture2D>("textured");
// Set the speed of the background
this.speed = speed;
// If we divide the screen with the texture width then we can determine the number of tiles need.
// We add 1 to it so that we won't have a gap in the tiling
//positions = new Vector2[screenWidth / texture.Width + 2];
texture = content.Load<Texture2D>("textured");
// Set the initial positions of the parallaxing background
for (int i = 0; i < screenWidth / texture.Width + 2; i++)
{
//Pull out random texture
Random random = new Random();
string[] randomHill = new string[2];
randomHill[0] = "textured";
randomHill[1] = "hillsmooth";
string currentString = randomHill[(int)(random.Next(0, 2))];
texture = content.Load<Texture2D>(currentString);
// We need the tiles to be side by side to create a tiling effect
positionsArray[i,0] = new Vector2(i * texture.Width, 290);
positionsArray[i, 1] = texture;
}
}
public void Update(ContentManager content)
{
Debug.WriteLine("=========================");
// Update the positions of the background
for (int i = 0; i < positionsArray.GetLength(0); i++)
{
Vector2 current_position = (Vector2)positionsArray[i, 0];
// Update the position of the screen by adding the speed
current_position.X += speed;
// Check the texture is out of view then put that texture at the end of the screen
if (current_position.X <= -texture.Width)
{
// Figure out a possibly new texture if it's out of view
Random random = new Random();
string[] newHill = new string[2];
newHill[0] = "textured";
newHill[1] = "hillsmooth";
string currentString = newHill[(int)(random.Next(0, 2))];
texture = content.Load<Texture2D>(currentString);
Color[] textureData = new Color[texture.Width * texture.Height];
texture.GetData(textureData);
current_position.X = texture.Width * (positionsArray.GetLength(0) - 1);
positionsArray[i, 1] = texture;
}
positionsArray[i, 0] = current_position;
}
}
public void Draw(SpriteBatch spriteBatch, ContentManager content)
{
for (int i = 0; i < positionsArray.GetLength(0); i++)
{
Vector2 current_position = (Vector2)positionsArray[i, 0];
//Random random = new Random();
//string[] hillsArray = new string[2];
//hillsArray[0] = "textured";
//hillsArray[1] = "hillsmooth";
//string currentString = hillsArray[(int)(random.Next(0,2))];
//texture = content.Load<Texture2D>(currentString);
texture = (Texture2D)positionsArray[i, 1];
spriteBatch.Draw(texture, current_position, Color.White);
}
}
}