Changing object textures in game engine "on the fly" (animated textures)

Hello!
I have animated object for Game Engine with 3 Shape actions.
I want to add yet another Shape action, but with another texture for this mesh.
Also I want to add fifth Shape action with animated texture.

I know that I can add other texture to the mesh using UV layers. And I can to change active UV layer (and texture) while I don’t run game. But can I change this in Game Engine?

Or may be there are other way to do this without creating new meshes?

Thanks!

So… Nobody knows… But now I know it :slight_smile:

To change texture in BGE “on the fly” (make animating texture) you need to do the next:

  1. Make UV-map
  2. Add texture to object’s material
  3. In Material Buttons -> Map Input don’t forget to set “UV” coordinates
  4. All textures for your animation put to different image files
  5. In Edit-mode select all faces. Make sure that in Editing (F9) -> Texture Face section set on “Tex” and “Light” modes (Light not need if you don’t want that the colors of objects changes on lighting). Also to make sure press “Copy” button to copy this settings for all faces (not only “active face”).
  6. To change texture on object use the next Python-code:

#here you must initialize “obj” variable – your object

import VideoTexture
#Select material
matID = VideoTexture.materialID(obj, “MAMaterial”
#Select first channel of textures
texture = VideoTexture.Texture(obj, matID, 0)
#Load image from file
texture.source = VideoTexture.ImageFFmpeg(“Path to image”)
#Update texture
texture.refresh(False)
#You need to save texture to object property. Else it will destroyed on the next tick.
obj[“Texture”] = texture

To not load texture from file every time you can save ImageFFmpeg() result to an object property.

More details on undocumented VideoTexture module see here.
Using VideoTexture module to implement mirror in BGE.

There is in attachment conceptual demo of changing texutures on cube for Blender 2.49. Put 5 files to a directory, and run Change_Textures_in_BGE.blend in blender.

Enjoy!

Attachments

Change_Textures_in_BGE.blend (147 KB)



Edited:, Your solution works perfectly!

PS. There is a minor error in your code - missing ) at the end of matId = VideoTexture.materialId
Regards.

omg you awesome !!!

is it possible to do this on multiple objects, but with them all using their own a specific image that they store themelves?
i have tried to do this but they all display the same image.

Yes, it’s possible. The script refers to a single image, though, so you would have to change the script to either have one separate script per object, or use an object property (stored in each object) of which image to use. Also, you have to use a different image for each object.

Nice! Really Nice! I was looking for this script!

Finally converted to be working on blender 2.61!!!

Great Work SolarLume!!! THANKS!

import bge
from bge import logic as GameLogic
from bge import events as GameKeys

# (C) unDEFER, June 2010 ported by Chewe3D 2012

scene = GameLogic.getCurrentScene()

co = GameLogic.getCurrentController()
obj = co.owner

def changeTexture(c):
	import VideoTexture
	#Select Material
	matID = VideoTexture.materialID(obj, "MAMaterial")
	#Select first texture channel
	texture = VideoTexture.Texture(obj, matID, 0)
	image = GameLogic.expandPath("//"+str(c)+".png")
	if not "tex" + str(c) in obj:
		#Load image from file
		obj["tex"+str(c)] = VideoTexture.ImageFFmpeg(image)
	texture.source = obj["tex"+str(c)]
	obj["Texture"] = texture
	obj["Texture"].refresh(False)

keylist = co.sensors["Keyboard"].events
for key in keylist:
	if key[1] == GameLogic.KX_INPUT_JUST_ACTIVATED:
		if key[0] == GameKeys.ONEKEY:
			obj["Frame"] = 1
		if key[0] == GameKeys.TWOKEY:
			obj["Frame"] = 2
		if key[0] == GameKeys.THREEKEY:
			obj["Frame"] = 3
		if key[0] == GameKeys.FOURKEY:
			obj["Frame"] = 4		
		obj["c"] = 0
		changeTexture(obj["Frame"])

if not "Frame" in obj:
	obj["Frame"] = 1

#c -- is Logic Tics Counter	
if not "c" in obj:
	obj["c"] = 0
	
obj["c"] = obj["c"] + 1
		
if obj["c"] > obj["Speed"] * bge.logic.getLogicTicRate():	
	obj["c"] = 0
	obj["Frame"] += 1
	
	if obj["Frame"] > 4:
		obj["Frame"] = 1
	
	changeTexture(obj["Frame"])