Проблема с тенью SKLightNode

Мне не удалось заставить SKSpriteNode отбрасывать тень, а также исчезать при попадании в тень от того же источника света. Я могу сделать одно из двух, но не оба.

Согласно документам: Если спрайт находится внутри тени, отбрасываемой источником света, и спрайт имеет более низкую позицию по оси z, чем источник света, тень влияет на то, как спрайт освещен. Все, что я сделал, я сделал. . Мой SKLightNode имеет zPosition 100, а все остальные узлы имеют более низкие zPositions.

Я пробовал любые комбинации настроек для 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

person sangony    schedule 22.02.2015    source источник


Ответы (2)


Я только что получил ответ от службы технической поддержки разработчиков Apple, подтверждающий, что это ошибка в SpriteKit (SKLightNode). В настоящее время они не знают обходного пути для этой проблемы, но сообщат мне, если он будет найден.

По их просьбе я подал отчет об ошибке.

ОБНОВЛЕНИЕ от 22 апреля 2015 г.

Инженеры SK подтвердили, что SpriteKit не поддерживает отбрасывание теней и затенение одного и того же объекта. В настоящее время нет обходного пути. Когда-нибудь этот вопрос будет решен.

ОБНОВЛЕНИЕ от 15 декабря 2015 г.

Получен новый ответ от Apple по этому вопросу.

Связи с разработчиками Apple, 14 декабря 2015 г., 13:35.

Планов по этому поводу нет.

Сейчас мы закрываем этот отчет.

person sangony    schedule 28.03.2015
comment
Я проверил это с помощью Xcode 8.3.2, и, похоже, это было исправлено. Я поместил ваш код в пример проекта, и тень от стены на синем поле скрывает его, как и ожидалось. Синяя коробка также по-прежнему отбрасывает собственную тень, если она не закрыта тенью стены. Возможно, это было исправлено в недавнем обновлении SK, или, может быть, я неправильно понимаю вашу проблему. - person BlueBear; 18.05.2017

Я нашел некоторое обходное решение (не уверен, что это полезно для всех ситуаций, но в некоторых): Вы можете сделать два (или больше - до 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;
person Maxim Krylov    schedule 23.04.2015
comment
Это не решение. Проблема в том, что узел отбрасывает тень, он не может быть затенен одновременно. Создание двух узлов не решает эту проблему, так как узел, отбрасывающий тень, не исчезнет в тени. - person sangony; 23.04.2015
comment
@sangony Я думаю, что обходной путь заключается в том, что вы дублируете свои источники света и спрайты. Таким образом, один источник света заставит спрайт отбрасывать тень, а другой источник света затенит второй спрайт (используя ту же текстуру) — и они будут друг над другом. Таким образом, один из спрайтов, отбрасывающих тень, не виден, так как он находится под вторым спрайтом, который отбрасывает тень. - person Seivan; 02.08.2019