【问题标题】:SKLightNode cast shadow issueSKLightNode 投射阴影问题
【发布时间】:2015-02-22 20:03:59
【问题描述】:

我未能成功让 SKSpriteNode 投射阴影,并且在从同一光源进入阴影时也会消失。我可以做到两者之一,但不能同时做。

根据文档:如果精灵在灯光投射的阴影内,并且精灵的 z 位置低于灯光,那么阴影会影响精灵的光照方式。我已经做好了。我的 SKLightNode 的 zPosition 为 100,所有其他节点的 zPosition 都较低。

我已经尝试了 lightingBitMask、shadowCastBitMask 和 shadowedBitMask 的所有设置组合,但没有任何效果。

我发布了重新创建我的问题的隔离代码。蓝色的盒子投下了阴影,但没有被墙影覆盖。紫色的盒子没有阴影,被墙影覆盖。

灯光会响应触摸移动,因此您可以随意在屏幕上移动它。该项目处于横向模式。

我错过了什么或没有看到什么?

#import "GameScene.h"

@implementation GameScene {
    SKSpriteNode *lightBulb;
}

-(void)didMoveToView:(SKView *)view {

    typedef NS_OPTIONS(uint32_t, Level1LightCategory)
    {
        CategoryLightPlayer            = 1 << 0,
    };

    SKSpriteNode *worldNode = [SKSpriteNode spriteNodeWithColor:[SKColor clearColor] size:CGSizeMake(1136, 640)];
    worldNode.zPosition = 10;
    //worldNode.position = CGPointMake(self.size.width/2, self.size.height/2);
    [self addChild:worldNode];

    lightBulb = [SKSpriteNode spriteNodeWithColor:[SKColor yellowColor] size:CGSizeMake(20, 20)];
    lightBulb.zPosition = 100;
    lightBulb.position = CGPointMake(50, 50);
    [worldNode addChild:lightBulb];

    SKLightNode *light = [[SKLightNode alloc] init];
    //light.zPosition = 100; // <- tried setting this again but to no effect
    light.categoryBitMask = CategoryLightPlayer;
    light.falloff = 0.3;
    light.ambientColor = [UIColor whiteColor];
    light.lightColor = [[UIColor alloc] initWithRed:1.0 green:1.0 blue:1.0 alpha:1.0];
    light.shadowColor = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:1.0];
    [lightBulb addChild:light];

    SKSpriteNode *wall = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(10, 300)];
    wall.zPosition = 50;
    wall.position = CGPointMake(500, 200);
    wall.lightingBitMask = CategoryLightPlayer;
    wall.shadowCastBitMask = CategoryLightPlayer;
    wall.shadowedBitMask = 0x00000000;
    [worldNode addChild:wall];

    SKSpriteNode *box0 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(30, 30)];
    box0.zPosition = 40;
    box0.position = CGPointMake(800, 200);
    box0.lightingBitMask = CategoryLightPlayer;
    box0.shadowCastBitMask = CategoryLightPlayer;
    box0.shadowedBitMask = CategoryLightPlayer;
    [worldNode addChild:box0];

    SKSpriteNode *box1 = [SKSpriteNode spriteNodeWithColor:[SKColor purpleColor] size:CGSizeMake(30, 30)];
    box1.zPosition = 40;
    box1.position = CGPointMake(800, 300);
    box1.lightingBitMask = CategoryLightPlayer;
    //box1.shadowCastBitMask = CategoryLightPlayer;
    //box1.shadowedBitMask = CategoryLightPlayer;
    [worldNode addChild:box1];  
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self.scene];

    lightBulb.position = touchLocation;
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInNode:self.scene];

    lightBulb.position = touchLocation;
}

-(void)update:(CFTimeInterval)currentTime {
    //
}

@end

【问题讨论】:

    标签: sprite-kit shadow skspritenode sklightnode


    【解决方案1】:

    我刚刚收到 Apple 开发人员技术支持的回复,确认这是 SpriteKit (SKLightNode) 中的一个错误。目前他们不知道这个问题的解决方法,但如果找到了会更新我。

    根据他们的要求,我已经提交了错误报告。

    2015 年 4 月 22 日更新

    SK 工程部门确认 SpriteKit 不支持阴影投射和在同一个对象上的阴影。目前没有解决方法。这个问题将在某个时候得到解决。

    2015 年 12 月 15 日更新

    收到 Apple 关于此问题的新回复。

    Apple 开发者关系 2015 年 12 月 14 日下午 1:35

    没有计划解决这个问题。

    我们现在关闭此报告。

    【讨论】:

    • 我使用 Xcode 8.3.2 对此进行了测试,它似乎已修复。我将您的代码放入一个示例项目中,并在蓝色框上的墙上投射阴影,按预期隐藏它。当没有被墙壁阴影覆盖时,蓝色盒子仍然会投射自己的阴影。也许这已在最近的 SK 更新中得到解决,或者我误解了您的问题。
    【解决方案2】:

    我找到了一些解决方法(不确定它是否适用于所有情况,但在某些情况下): 您可以制作两个(或更多——我们知道的最多 32 个)不同的光源,并一个一个地(或按一些组)将精灵分配给它们。然后阴影将根据需要组合 - 正确。

    SKLightNode* light1 = [SKLightNode new];
    SKLightNode* light2 = [SKLightNode new];
    
    ... // init them equally
    
    light1.categoryBitMask = 1;
    light2.categoryBitMask = 2;
    ...
    
    SKSpriteNode* sprite1 = ...
    SKSpriteNode* sprite2 = ...
    
    sp1.shadowCastBitMask = 1;
    sp1.shadowedBitMask = 1;
    sp2.shadowCastBitMask = 2;
    sp2.shadowedBitMask = 2;
    

    【讨论】:

    • 这不是解决方案。问题是一个节点投射阴影,它不能同时被阴影。创建2个节点并不能解决它,因为投射阴影的节点不会消失在阴影中。
    • @sangony 我认为解决方法是复制灯光和精灵。因此,一盏灯将使精灵投射阴影,另一盏灯将遮住第二个精灵(使用相同的纹理)——它们将在彼此之上。因此,其中一个精灵投射阴影是不可见的,因为它位于第二个下方 - 确实投射了阴影。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-20
    • 2016-06-21
    • 1970-01-01
    • 2013-08-03
    • 1970-01-01
    相关资源
    最近更新 更多