# Dynamically create sprite from texture or update sprite's texture on runtime

**URL:** <https://forums.unrealengine.com/t/dynamically-create-sprite-from-texture-or-update-sprites-texture-on-runtime/382073>\
**Category:** Asset Creation\
**Tags:** sprites, unreal-engine, runtime, question\
**Created:** [January 17, 2017, 12:47am UTC](https://forums.unrealengine.com/t/dynamically-create-sprite-from-texture-or-update-sprites-texture-on-runtime/382073 "2017-01-17T00:47:49Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Luciano\_Santos](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Luciano\_Santos](https://forums.unrealengine.com/u/Luciano_Santos)\
**Post date:** [January 17, 2017, 12:47am UTC](https://forums.unrealengine.com/t/dynamically-create-sprite-from-texture-or-update-sprites-texture-on-runtime/382073/1 "2017-01-17T00:47:49Z")

</div>

I’m sorry if this question is dumb, but I’ve been googling for 2 days now and wasn’t able to get it to work. I’m using the HTTP module to download an image and create a texture dynamically at runtime, using UTexture2D::CreateTransient(). I’d then like to update a PaperSpriteActor to show this texture. After a lot of messing around, I first created a DynamicPaperSprite that simply adds one method SetTexture to PaperSprite:

```
void UDynamicPaperSprite::SetTexture(UTexture2D* Texture)
{
	SourceTexture = Texture;
	SourceDimension.Set(Texture->GetSizeX(), Texture->GetSizeY());
	SourceUV.Set(0, 0);
	PixelsPerUnrealUnit = 1.0f;
	PostLoad();
	GEngine->AddOnScreenDebugMessage(-1, 20.0f, FColor::Red, FString(TEXT("Done DynamicPaperSprite->SetTexture")));
}

```

Then, on my DynamicPaperSpriteActor, I do this:

```
void ADynamicPaperSpriteActor::UpdateTexture(UTexture2D* Texture)
{
	UPaperRenderComponent* Render = Super::GetRenderComponent();
	Render->SetMobility(EComponentMobility::Stationary);
	UDynamicPaperSprite* Sprite = dynamic_cast<UDynamicPaperSprite*>(Render->GetSprite());
	if (!Sprite)
		Sprite = NewObject<UDynamicPaperSprite>();
	Sprite->SetTexture(Texture);
	Render->SetSprite(Sprite);
}

```

When I run this, the game successfully sets up the new sprite on my actor. However, the created sprite is completely blank. I’m sure the image I’m downloading is not blank, I’ve tested this. Any ideas?

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![Luciano\_Santos](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Luciano\_Santos](https://forums.unrealengine.com/u/Luciano_Santos)\
**Post date:** [January 17, 2017, 11:20am UTC](https://forums.unrealengine.com/t/dynamically-create-sprite-from-texture-or-update-sprites-texture-on-runtime/382073/2 "2017-01-17T11:20:59Z")

</div>

OK, so I figured it out. I also had to update the BakedRenderData internal field. So my final DynamicPaperSprite code looks like this (fixed pivot, full source image, no transformations possible):

```
UDynamicPaperSprite::UDynamicPaperSprite(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	SpriteCollisionDomain = ESpriteCollisionMode::None;
	PixelsPerUnrealUnit = 1.0f;
	RenderGeometry.GeometryType = ESpritePolygonMode::SourceBoundingBox;
}

void UDynamicPaperSprite::SetTexture(UTexture2D* Texture)
{
	if (Texture)
	{
		float Width = Texture->GetSizeX();
		float Height = Texture->GetSizeY();

		SourceTexture = Texture;
		SourceUV.Set(0, 0);
		SourceDimension.Set(Width, Height);

		const FVector2D Pivot = GetPivotPosition();
		BakedRenderData.Empty(6);

		// Uses 2 triangles to describe the mesh.
		// Each vertex is in the format: [ImageX relative to Pivot, ImageY relative to Pivot, U, V]
		BakedRenderData.Add(FVector4(0.0f - Pivot.X, Pivot.Y - 0.0f, 1.0f, 0.0f));
		BakedRenderData.Add(FVector4(Width - Pivot.X, Pivot.Y - 0.0f, 0.0f, 0.0f));
		BakedRenderData.Add(FVector4(Width - Pivot.X, Pivot.Y - Height, 0.0f, 1.0f));

		BakedRenderData.Add(FVector4(0.0f - Pivot.X, Pivot.Y - 0.0f, 1.0f, 0.0f));
		BakedRenderData.Add(FVector4(Width - Pivot.X, Pivot.Y - Height, 0.0f, 1.0f));
		BakedRenderData.Add(FVector4(0.0f - Pivot.X, Pivot.Y - Height, 1.0f, 1.0f));
	}
}

```

---

<div class="post-metadata">

**Author:** ![neofuturelabs](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/neofuturelabs/32/1194562_2.png) [@neofuturelabs](https://forums.unrealengine.com/u/neofuturelabs)\
**Post date:** [October 26, 2017, 4:45am UTC](https://forums.unrealengine.com/t/dynamically-create-sprite-from-texture-or-update-sprites-texture-on-runtime/382073/3 "2017-10-26T04:45:50Z")

</div>

Thanks for posting how you solved this!

I just had to implement something similar (engine ver. 4.17), but I wanted to note that the Sprite’s visuals wouldn’t update after changing the texture without also calling MarkRenderStateDirty() on the UPaperSpriteComponent containing the Sprite. I suppose that SetSprite would do the same thing internally, but in my situation I don’t need the physics state or bounds etc to update, so this is a bit lighter weight. This way, the mobility also doesn’t need to be fiddled with.

---

<div class="post-metadata">

**Author:** ![neofuturelabs](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/neofuturelabs/32/1194562_2.png) [@neofuturelabs](https://forums.unrealengine.com/u/neofuturelabs)\
**Post date:** [December 3, 2017, 6:02am UTC](https://forums.unrealengine.com/t/dynamically-create-sprite-from-texture-or-update-sprites-texture-on-runtime/382073/4 "2017-12-03T06:02:47Z")

</div>

One more thing, the following variables/functions are contained within a “#if WITH\_EDITORONLY\_DATA” macro in the UPaperSprite base class, so build errors occur when packaging (as the editor is not included in packaged builds):

- RenderGeometry

- GetPivotPosition()

These errors can be resolved as follows:

- “RenderGeometry.GeometryType = ESpritePolygonMode::SourceBoundingBox;” can be safely removed without any issues

- “const FVector2D Pivot = GetPivotPosition();” can be replaced by the following (this is basically a copy of the GetPivotPosition() code for the Center\_Center PivotMode, which is the only type I am using)

* * *

```
const FVector2D RawPivot = FVector2D(SourceUV.X + SourceDimension.X * 0.5f, SourceUV.Y + SourceDimension.Y * 0.5f);

FVector2D Pivot = RawPivot;

Pivot.X = FMath::RoundToFloat(Pivot.X);

Pivot.Y = FMath::RoundToFloat(Pivot.Y);
```

---

<div class="post-metadata">

**Author:** ![Denis\_Frolov](https://d3kjluh73b9h9o.cloudfront.net/original/4X/2/8/5/28502927f1d97ba1051b3b47ccfe17233bf41ef0.png) [@Denis\_Frolov](https://forums.unrealengine.com/u/Denis_Frolov)\
**Post date:** [March 20, 2025, 1:00am UTC](https://forums.unrealengine.com/t/dynamically-create-sprite-from-texture-or-update-sprites-texture-on-runtime/382073/5 "2025-03-20T01:00:29Z")

</div>

I’ve been looking for a way to create sprites at runtime for a while, and this answer was a godsend. But I’ll add to this ancient question in case anyone needs it, because it’s not all smooth sailing at least on UE 4.27.

- First, the BakedRenderData parameters provided here will make your texture horizontally mirrored.

- Second, as neofuturelabs noted, RenderGeometry and GetPivotPosition() will crash the package project because they are wrapped in the “#if WITH\_EDITORONLY\_DATA” macro. But the same macro also wraps the variables: SourceTexture, SourceUV and SourceDimension. Using any of these variables will also prevent you from packaging the project. You can get around this by using their Baked versions.

- Thirdly, it is worth noting that many materials will work with the resulting sprites differently than with sprites made through the editor. In particular, materials with Blend Mode equal to Masked always lead to a complete blackening of the texture. I still haven’t figured out how to fix this, so I just started using only Blend Mode: Translucent.

Here is my modified version of the SetTexture function in DynamicPaperSprite with the ability to select SpritePivotMode (except Custom):

```auto
void UDynamicPaperSprite::SetTexture(UTexture2D* Texture, ESpritePivotMode::Type Pivot)
{
	if (Texture){
		float Width = Texture->GetSizeX();
		float Height = Texture->GetSizeY();

		BakedSourceTexture = Texture;
		BakedSourceUV.Set(0, 0);
		BakedSourceDimension.Set(Width, Height);

		FVector2D RawPivot;
		switch (Pivot)
		{
		case ESpritePivotMode::Top_Left:
			RawPivot = FVector2D(BakedSourceUV.X, BakedSourceUV.Y);
			break;
		case ESpritePivotMode::Top_Center:
			RawPivot = FVector2D(BakedSourceUV.X + BakedSourceDimension.X * 0.5f, BakedSourceUV.Y);
			break;
		case ESpritePivotMode::Top_Right:
			RawPivot = FVector2D(BakedSourceUV.X + BakedSourceDimension.X, BakedSourceUV.Y);
			break;
		case ESpritePivotMode::Center_Left:
			RawPivot = FVector2D(BakedSourceUV.X, BakedSourceUV.Y + BakedSourceDimension.Y * 0.5f);
			break;
		case ESpritePivotMode::Center_Center:
			RawPivot = FVector2D(BakedSourceUV.X + BakedSourceDimension.X * 0.5f, BakedSourceUV.Y + BakedSourceDimension.Y * 0.5f);
			break;
		case ESpritePivotMode::Center_Right:
			RawPivot = FVector2D(BakedSourceUV.X + BakedSourceDimension.X, BakedSourceUV.Y + BakedSourceDimension.Y * 0.5f);
			break;
		case ESpritePivotMode::Bottom_Left:
			RawPivot = FVector2D(BakedSourceUV.X, BakedSourceUV.Y + BakedSourceDimension.Y);
			break;
		case ESpritePivotMode::Bottom_Center:
			RawPivot = FVector2D(BakedSourceUV.X + BakedSourceDimension.X * 0.5f, BakedSourceUV.Y + BakedSourceDimension.Y);
			break;
		case ESpritePivotMode::Bottom_Right:
			RawPivot = FVector2D(BakedSourceUV.X + BakedSourceDimension.X, BakedSourceUV.Y + BakedSourceDimension.Y);
			break;
		default:
			RawPivot = FVector2D(BakedSourceUV.X + BakedSourceDimension.X * 0.5f, BakedSourceUV.Y + BakedSourceDimension.Y * 0.5f);
			break;
		}
		
		FVector2D Pivot = RawPivot;
		Pivot.X = FMath::RoundToFloat(Pivot.X);
		Pivot.Y = FMath::RoundToFloat(Pivot.Y);

		BakedRenderData.Empty(6);

		BakedRenderData.Add(FVector4(0.0f - Pivot.X, Pivot.Y - 0.0f, 0.0f, 0.0f));
		BakedRenderData.Add(FVector4(Width - Pivot.X, Pivot.Y - 0.0f, 1.0f, 0.0f));
		BakedRenderData.Add(FVector4(Width - Pivot.X, Pivot.Y - Height, 1.0f, 1.0f));

		BakedRenderData.Add(FVector4(0.0f - Pivot.X, Pivot.Y - 0.0f, 0.0f, 0.0f));
		BakedRenderData.Add(FVector4(Width - Pivot.X, Pivot.Y - Height, 1.0f, 1.0f));
		BakedRenderData.Add(FVector4(0.0f - Pivot.X, Pivot.Y - Height, 0.0f, 1.0f));
	}
}

```

I hope this will be useful to someone.

---

<div class="post-metadata">

**Author:** ![SolarflareSoft](https://d1ap1mz92jnks1.cloudfront.net/user_avatar/forums.unrealengine.com/solarflaresoft/32/1192396_2.png) [@SolarflareSoft](https://forums.unrealengine.com/u/SolarflareSoft)\
**Post date:** [August 4, 2026, 7:34pm UTC](https://forums.unrealengine.com/t/dynamically-create-sprite-from-texture-or-update-sprites-texture-on-runtime/382073/6 "2026-08-04T19:34:32Z")

</div>

Just noting (in case someone else stumbles on this) that the modified version still won’t work, because the `ESpritePivotMode::Type` enum is not defined in Shipping builds. Therefore, you have three choices:

1. Choose a specific pivot mode and always use it. Maybe it’s fine just to always use `Center_Center`, for example.
2. Pass the pivot as an `FVector2D`. This eliminates the entire switch statement.
3. Define your own custom enum that has the same values as `ESpritePivotMode::Type` but is defined in Shipping builds.
