SKLightNode投射阴影问题
SKLightNode cast shadow issue
我一直未能成功让 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
我刚刚收到 Apple 开发人员技术支持的回复,确认这是 SpriteKit (SKLightNode) 中的错误。目前他们不知道这个问题的解决方法,但如果找到的话会更新我。
应他们的要求,我已提交错误报告。
更新 2015 年 4 月 22 日
SK engineering 确认 SpriteKit 不支持在同一对象上投射阴影。目前没有解决方法。此问题将在某个时候得到解决。
更新 2015 年 12 月 15 日
已收到 Apple 关于此问题的新回复。
Apple Developer Relations 14-Dec-2015 01:35 PM
There are no plans to address this.
We are now closing this report.
我找到了一些解决方法(不确定它是否适用于所有情况,但在某些情况下):
您可以制作两个(或更多 - 我们知道最多 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;
我一直未能成功让 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
我刚刚收到 Apple 开发人员技术支持的回复,确认这是 SpriteKit (SKLightNode) 中的错误。目前他们不知道这个问题的解决方法,但如果找到的话会更新我。
应他们的要求,我已提交错误报告。
更新 2015 年 4 月 22 日
SK engineering 确认 SpriteKit 不支持在同一对象上投射阴影。目前没有解决方法。此问题将在某个时候得到解决。
更新 2015 年 12 月 15 日
已收到 Apple 关于此问题的新回复。
Apple Developer Relations 14-Dec-2015 01:35 PM
There are no plans to address this.
We are now closing this report.
我找到了一些解决方法(不确定它是否适用于所有情况,但在某些情况下): 您可以制作两个(或更多 - 我们知道最多 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;