How to have a red "you got hit" effect?

In a 3d scene, how do I create an effect like this?

My initial thought for a simpler version of this was to find the extent of the camera, then draw a series of boxes that get smaller and more transparent, so you’d get about an inch of this effect at the edge of the screen. But I can’t even get a line to render at the moment; if I choose the UI layer, nothing happens, and if I choose the world layer everything goes black:

PickerRaycast.prototype.onSelect = function (x, y) {
    var from = this.entity.camera.screenToWorld(x, y, this.entity.camera.nearClip);
    var to = this.entity.camera.screenToWorld(x, y, this.entity.camera.farClip);
    var pickedEntity = this.app.systems.rigidbody.raycastFirst(from, to); 
    if (pickedEntity && pickedEntity.entity.name == 'TargetModel') {
        //console.log("selected correct model");
        // trigger positive feedback animations        
    } else {
        // trigger negative feedback
        var start = new pc.Vec3(0, x, y);
        var end = new pc.Vec3(1, x+100, y+100);
        var color = new pc.Color(1, 1, 1);
        var UILayer = this.app.scene.layers.getLayerById(pc.LAYERID_UI);
        this.app.renderLine(start, end, color, {
            layer: UILayer
        });
    }
};

line rendering to world layer is broken … we have an issue opened for this. Use pc.LAYERID_IMMEDIATE instead (which is a default if you don’t specify a layer). But note that coordinates need to be in world space for it I believe.

1 Like

you could just fire an event that activates a red 2d image around the screen

Yeah that’s probably what I will end up doing. Still, it would have been cool if I could have figured out how to generate it with code.

You could use the procedure mesh API and generate a bunch of triangles. Texture then with an image that I s solid colour in the middle and fades out to the edge.

That should get you pretty close if you wanted a code only solution.

It would also give you room to make it random too by shifting the triangle point

1 Like

I went with a simple fade in approach for now. Will revist when I’ve got more experience. Here’s the snippet in case it helps someone else.

PickerRaycast.prototype.initialize = function() {
    // red border settings
    this.redBorderMaxOpacity = 0.5;
    this.redBorder.enabled = false;
    this.redBorder.element.opacity = 0;
    this.redBorderFrames = 25;  
    this.redBorderOpacityIncrement = this.redBorderMaxOpacity/(this.redBorderFrames/2);    
    this.redBorderFadeIn = true;        
};

PickerRaycast.prototype.onSelect = function (x, y) {    
    var from = this.entity.camera.screenToWorld(x, y, this.entity.camera.nearClip);
    var to = this.entity.camera.screenToWorld(x, y, this.entity.camera.farClip);
    var pickedEntity = this.app.systems.rigidbody.raycastFirst(from, to); 
    if (pickedEntity && pickedEntity.entity.name == 'TargetModel') {
        // target model clicked, positive feedback
    } else {
        if (this.messageAfter.enabled === false) {
            this.redBorder.enabled = true;   
        }
    }
};

PickerRaycast.prototype.update = function(dt) {
    // if red border is enabled, fade it in, then fade it out.
    if (this.redBorder.enabled === true) {        
        if (this.redBorderFadeIn === true && this.redBorder.element.opacity <= this.redBorderMaxOpacity) {            
            this.redBorder.element.opacity += this.redBorderOpacityIncrement;            
        } else if (this.redBorder.element.opacity >= this.redBorderMaxOpacity || this.redBorderFadeIn === false && this.redBorder.element.opacity > 0) {            
            this.redBorderFadeIn = false;
            this.redBorder.element.opacity -= this.redBorderOpacityIncrement;            
        } else if (this.redBorder.element.opacity <= 0) {            
            this.redBorder.enabled = false;
            this.redBorderFadeIn = true;            
        }
    }
};