[Spine] Help locating error, sim/device inconsistent

I posted this issue to the Esoteric forums, but since the issue seems to be on Corona’s side, I wanted to see if anyone here could give additional input.  You can see the original post here.

I am having some issues with animations not running and with runtime errors on devices. I’ll try to detail the issues and provide appropriate code. Maybe I am overlooking something simple that someone more familiar with spine will recognize.

Running in the Corona simulator, most animations run fine, including unit idle animations, etc. The only visible issue is that some attack animations simply do not play at all. There is inconsistency in this as the attack will play for one unit but not the other, even though they are loading the same spine json and visual assets. There are NO errors logged in the console or any indication that there is a problem. This is also a recent issue as at some point, all animations were running fine.

When running on android devices, there are many issues with the animations. Idle animations are seemingly random, some animate some don’t. There is no consistency as to which work based on unit types, positions, etc even between turns. Some attachments do not appear at all or disappear after a non-idle animation. The non-animating attacks from the sim still do not animate. Reading the logs show this runtime error being spammed to the console:

I/Corona (20725): Runtime error
I/Corona (20725):
I/Corona (20725): stack traceback:
I/Corona (20725):     [C]: in function ‘removeSelf’
I/Corona (20725):     …-Brawl(default)\Monster-Brawl\spine-corona\spine.lua:110: in function ‘updateWorldTransform’
I/Corona (20725):     …onster-Brawl(default)\Monster-Brawl\modules\unit.lua:264: in function ‘updateAnim’
I/Corona (20725):     …Monster-Brawl(default)\Monster-Brawl\gamemanager.lua:671: in function

<…Monster-Brawl(default)\Monster-Brawl\gamemanager.lua:665>
I/Corona (20725):     ?: in function <?:218>

The code traces back to this line in spine.lua:

if image and image.attachment ~= attachment then -- Attachment image has changed. &nbsp; if self:modifyImage(image, attachment) then &nbsp;&nbsp; &nbsp;&nbsp; image.lastR, image.lastA = nil, nil image.attachment = attachment else -- If not modified, remove the image and it will be recreated. image:removeSelf() -- this is line 110\*\*\*\*\*\*\*\*\*\* images[slot] = nil image = nil end end

My enterframe code calculates delta once, then calls this function for each existing unit:

function unit:updateAnim(delta) self.sprite.animState:update(delta) self.sprite.animState:apply(self.sprite) self.sprite:updateWorldTransform() end

Here is how the spines are being created within the unit module:

function unit.new(unitType, iff, position, hp, cd, eq) local newUnit = {} createUnitData(newUnit, unitType, iff, position, hp, eq) newUnit.sprite = createUnitSpine(newUnit) return setmetatable(newUnit, unit\_mt) end

The createUnitSpine function is local to the module. The relevant code portions look like:

local function createUnitSpine(newUnit) local spine = require('spine-corona.spine') local spinePath = 'assets/visual/animations/'..newUnit.model.spine..'/' local skinPath = spinePath..newUnit.model.skin..'/' local jsonSpine = spine.SkeletonJson.new() jsonSpine.scale = 1 local skeletonData = jsonSpine:readSkeletonDataFile(spinePath..newUnit.model.spine..'.json') local sprite = spine.Skeleton.new(skeletonData) function sprite:createImage(attachment) return display.newImageRect(skinPath..attachment.name..'.png', attachment.width, attachment.height) end sprite:setToSetupPose() -- AnimationStateData defines crossfade durations between animations sprite.animStateData = spine.AnimationStateData.new(skeletonData) -- Set up to create transitions between ALL animations in table below local animStates = {'idle','hurt','select','dead'} local animTransTime = 0.3 -- common length for all transitions for i=1,#animStates do for j=1,#animStates do sprite.animStateData:setMix(animStates[i], animStates[j], animTransTime) end sprite.animStateData:setMix(animStates[i], 'attack1', animTransTime) sprite.animStateData:setMix(animStates[i], 'attack2', animTransTime) sprite.animStateData:setMix(animStates[i], 'attack3', animTransTime) sprite.animStateData:setMix(animStates[i], 'attack4', animTransTime) end -- AnimationState keeps queue of animations and applies via crossfading sprite.animState = spine.AnimationState.new(sprite.animStateData) sprite.animState:setAnimationByName(0,'idle', true) return sprite end

Does anything look out of sorts? Why am I not seeing any runtime errors in the simulator? Any help or advice is appreciated. Thanks.

In another post, Rob Miracle says:

When ever I hear “It works in the simulator but not the device”, it tells me that there is a 90% chance you have a file name problem.  Devices are case sensitive, Windows and OS-X are not.

Boy was he right.

Apparently, Git (on Windows at least) is also not case sensitive.  Even if filename cases have been corrected, if they are pushed to the repository, it will not recognize the change and use the pre-existing case condition.  This caused some of our image assets that Spine was looking for appear to be ‘missing’ and not allowing the app to create and manipulate those images.

In another post, Rob Miracle says:

When ever I hear “It works in the simulator but not the device”, it tells me that there is a 90% chance you have a file name problem.  Devices are case sensitive, Windows and OS-X are not.

Boy was he right.

Apparently, Git (on Windows at least) is also not case sensitive.  Even if filename cases have been corrected, if they are pushed to the repository, it will not recognize the change and use the pre-existing case condition.  This caused some of our image assets that Spine was looking for appear to be ‘missing’ and not allowing the app to create and manipulate those images.