Kinematic object does not detect any collisions - Godot - input

I am learning Godot game engine and I tried to make a ball that can walk and can't go through other objects, but the ball keep going through the other objects.
Here is the code:
extends KinematicBody2D
export var viteza = 140
func _ready():
set_fixed_process(true)
func _fixed_process(delta):
delta *= 5
var motion = Vector2()
if Input.is_key_pressed(KEY_UP):
motion[0] = 0
motion[1] = -1
if Input.is_key_pressed(KEY_DOWN):
motion[0] = 0
motion[1] = 1
if Input.is_key_pressed(KEY_LEFT):
motion[0] = -1
motion[1] = 0
if Input.is_key_pressed(KEY_RIGHT):
motion[0] = 1
motion[1] = 0
motion = motion * viteza * delta
set_pos(get_pos() + motion)
The scene (image):
Scene
What is wrong?

Never use set_pos() in a KinematicBody2D. You need to use move().

Related

Why doesn't the player fall down?

I'm making my first mobile game on godot so I'm very inexperienced. It is a platformer. I would like the player, when he collides with the enemy, to fall down and die. I've been trying to do it for days, but it always gives me some different problem and I don't understand what I'm doing wrong. Could anyone help me please? I leave you the player code; in this way the player, despite having set velocity.y=.500, does not fall, but makes a sort of jump. What's wrong? Thank you all in advance.
PLAYER CODE:
extends KinematicBody2D
onready var rayS = get_node("rayL")
onready var rayD = get_node("rayR")
onready var sprite = get_node("AnimatedSprite")
var alive = true
signal dead
const WALK_FORCE = 600
const WALK_MAX_SPEED = 300
const STOP_FORCE = 1300
const JUMP_SPEED = 700
const gravity = 1100.0
var velocity = Vector2()
func _physics_process(delta):
var force = Vector2(0, gravity)
var walk_left = Input.is_action_pressed("move_left") and alive
var walk_right = Input.is_action_pressed("move_right") and alive
var jump = Input.is_action_pressed("jump") and alive
# Horizontal movement code. First, get the player's input.
var walk = WALK_FORCE * (Input.get_action_strength("move_right") - Input.get_action_strength("move_left"))
# Slow down the player if they're not trying to move.
if abs(walk) < WALK_FORCE * 0.2:
# The velocity, slowed down a bit, and then reassigned.
velocity.x = move_toward(velocity.x, 0, STOP_FORCE * delta)
else:
velocity.x += walk * delta
# Clamp to the maximum horizontal movement speed.
velocity.x = clamp(velocity.x, -WALK_MAX_SPEED, WALK_MAX_SPEED)
# Vertical movement code. Apply gravity.
velocity.y += gravity * delta
# Move based on the velocity and snap to the ground.
velocity = move_and_slide_with_snap(velocity, Vector2.DOWN, Vector2.UP)
# Check for jumping. is_on_floor() must be called after movement code.
if is_on_floor() and Input.is_action_just_pressed("jump"):
jumping()
var on_floor = rayL.is_colliding() or rayR.is_colliding()
if walk_right:
sprite.set_flip_h(false)
if walk_left:
sprite.set_flip_h(true)
if (walk_left or walk_right) and on_floor:
sprite.play()
elif (walk_left or walk_right):
sprite.stop()
sprite.set_frame(3)
else:
sprite.stop()
sprite.set_frame(1)
if position.y > 900: dying()
func _on_Area2D_body_entered(body):
if not alive: return
jumping()
body.destroy()
func jumping():
velocity.y = -JUMP_SPEED
func _on_Area2D2_body_entered(body):
if not alive: return
dying()
func dying():
if not alive: return
alive = false
velocity.y = -500
collision_mask -= 2
emit_signal("dead")
In 2D, moving UP direction is negative on the y axis. Said another way, the Y axis is pointing downwards.
Thus, setting the velocity like this:
velocity.y = -500
Will result in upward motion, not downwards.

Model Shakes when moved long distance - Godot

I am making a space game in Godot and whenever my ship is a big distance away from (0,0,0) every time I move the camera or the ship, it shakes violently. Here is my code for moving the ship:
extends KinematicBody
export var default_speed = 500000
export var max_speed = 5000
export var acceleration = 100
export var pitch_speed = 1.5
export var roll_speed = 1.9
export var yaw_speed = 1.25
export var input_response = 8.0
var velocity = Vector3.ZERO
var forward_speed = 0
var vert_speed = 0
var pitch_input = 0
var roll_input = 0
var yaw_input = 0
var alt_input = 0
var system = "System1"
func _ready():
look_at(get_parent().get_node("Star").translation, Vector3.UP)
func get_input(delta):
if Input.is_action_pressed("boost"):
max_speed = 299792458
acceleration = 100
else:
max_speed = default_speed
acceleration = 100
if Input.is_action_pressed("throttle_up"):
forward_speed = lerp(forward_speed, max_speed, acceleration * delta)
if Input.is_action_pressed("throttle_down"):
forward_speed = lerp(forward_speed, 0, acceleration * delta)
pitch_input = lerp(pitch_input, Input.get_action_strength("pitch_up") - Input.get_action_strength("pitch_down"), input_response * delta)
roll_input = lerp(roll_input, Input.get_action_strength("roll_left") - Input.get_action_strength("roll_right"), input_response * delta)
yaw_input = lerp(yaw_input, Input.get_action_strength("yaw_left") - Input.get_action_strength("yaw_right"), input_response * delta)
func _physics_process(delta):
get_input(delta)
transform.basis = transform.basis.rotated(transform.basis.z, roll_input * roll_speed * delta)
transform.basis = transform.basis.rotated(transform.basis.x, pitch_input * pitch_speed * delta)
transform.basis = transform.basis.rotated(transform.basis.y, yaw_input * yaw_speed * delta)
transform.basis = transform.basis.orthonormalized()
velocity = -transform.basis.z * forward_speed * delta
move_and_collide(velocity * delta)
func _on_System1_area_entered(area):
print(area, area.name)
system = "E"
func _on_System2_area_entered(area):
print(area, area.name)
system = "System1"
Is there any way to prevent this from happening?
First of all, I want to point out, that this is not a problem unique to Godot. Although other engines have automatic fixes for it.
This happens because the precision of floating point numbers decreases as it goes away form the origin. In other words, the gap between one floating number and the next becomes wider.
The issue is covered in more detail over the game development sister site:
Why loss of floating point precision makes rendered objects vibrate?
Why does the resolution of floating point numbers decrease further from an origin?
What's the largest "relative" level I can make using float?
Why would a bigger game move the gameworld around the Player instead of just moving a player within a gameworld?
Moving player inside of moving spaceship?
Spatial Jitter problem in large unity project
Godot uses single precision. Support for double precision has been added in Godot 4, but that just reduces the problem, it does not eliminate it.
The general solution is to warp everything, in such way that the player is near the origin again. So, let us do that.
We will need a reference to the node we want to keep near the origin. I'm going to assume which node it is does not change during game play.
export var target_node_path:NodePath
onready var _target_node:Spatial = get_node(target_node_path)
And we will need a reference to the world we need to move. I'm also assuming it does not change. Furthermore, I'm also assuming the node we want to keep near the origin is a child of it, directly or indirectly.
export var world_node_path:NodePath
onready var _world_node:Node = get_node(target_node_path)
And we need a maximum distance at which we perform the shift:
export var max_distance_from_origin:float = 10000.0
We will not move the world itself, but its children.
func _process() -> void:
var target_origin := _target_node.global_transform.origin
if target_origin.length() < max_distance_from_origin:
return
for child in _world_node.get_children():
var spatial := child as Spatial
if spatial != null:
spatial.global_translate(-target_origin)
Now, something I have not seen discussed is what happens with physics objects. The concern is that The physics server might be trying to move them in the old position (in practice this is only a problem with RigidBody), and it will overwrite what we did.
So, if that is a problem… We can handle physic objects with a teleport. For example:
func _process() -> void:
var target_origin := _target_node.global_transform.origin
if target_origin.length() < max_distance_from_origin:
return
for child in _world_node.get_children():
var spatial := child as Spatial
if spatial != null:
var body_transform := physics_body.global_transform
var new_transform := Transform(
body_transform.basis,
body_transform.origin - target_origin
)
spatial.global_transform = new_transform
var physics_body := spatial as PhysicsBody # Check for RigidBody instead?
if physics_body != null:
PhysicsServer.body_set_state(
physics_body.get_rid(),
PhysicsServer.BODY_STATE_TRANSFORM,
new_transform
)
But be aware that the above code does not consider any physics objects deeper in the scene tree.

Basic movement 3D code not working properly

I wrote some code down for a kinematic character and only the W key(forward) worked, when I pressed w and d or a that's` when it starts moving but slowly goes left or right. Does anybody know how to fix this?
extends KinematicBody
var gravity =Vector3.DOWN * 12
var speed = 4
var jump_speed = 6
var spin = 0.1
var velocity = Vector3()
func _physics_process(delta):
velocity += gravity * delta
get_input()
velocity = move_and_slide(velocity,Vector3.UP)
func get_input():
velocity.x = 0
velocity.z = 0
if Input.is_action_pressed("move_UP"):
velocity.z -= speed
if Input.is_action_pressed("move_DOWN"):
velocity.x -= speed
if Input.is_action_pressed("strafe_Right"):
velocity.x -= speed
if Input.is_action_pressed("strafe_Left"):
velocity.z -= speed
func _unhandled_input(event):
if event is InputEventMouseMotion:
rotate_y(-lerp(0, spin, event.relative.x/10))
Um. Python code? Blocks are controlled by indentation. You've indented all your motion conditionals after move_UP so that they can only be executed if move_UP is active and executed first. Unindent the three "If" statements under the move_UP statement...

ARKit – Spatial Audio barely changes the volume over distance

I created a SCNNode and added an Audio to it.
It is a Mono audio. Everything is set up correctly.
It is working as Spatial Audio, that's not the problem.
The problem is that as i get closer or far away it barely changes the volume. I know it changes if i get very very far away, but it's nothing like Apple demonstrated here:
https://youtu.be/d9kb1LfNNU4?t=23
Some other games i see the audio volume really changing from one step distance.
With mine, with one step you can't even tell the volume changed. You need at least 4 steps.
Anyone has any clue why?
Code bellow:
SCNNode *audioNode = [[SCNNode alloc] init];
SCNAudioSource *audioSource = [[SCNAudioSource alloc] initWithFileNamed:audioFileName];
audioSource.loops = YES;
[audioSource load];
audioSource.volume = 0.05; // <-- i used different values. won't change much either
audioSource.positional = YES;
//audioSource.shouldStream = NO; // <-- makes no difference
[audioNode addAudioPlayer:[SCNAudioPlayer audioPlayerWithSource:audioSource]];
[audioNode runAction:[SCNAction playAudioSource:audioSource waitForCompletion:NO] completionHandler:nil];
[massNode addChildNode:audioNode];
Maybe scale of the nodes?
The whole scene is the size of around 4 feet.
When i add an object i usually scale it to 0.005 (otherwise it gets way too big).
But i also tried with one that was already in the right size from .scn file.
It shouldn't affect anything tho, since the result is a coffee table size scene and i can see the objects alright.
Updated.
Here's a working code for controlling sound's decay (works in iOS and macOS):
import AVFoundation
import ARKit
class ViewController: UIViewController, AVAudioMixing {
#IBOutlet var sceneView: SCNView!
// #IBOutlet var sceneView: ARSCNView!
func destination(forMixer mixer: AVAudioNode,
bus: AVAudioNodeBus) -> AVAudioMixingDestination? {
return nil
}
var volume: Float = 0.0
var pan: Float = 0.0
var sourceMode: AVAudio3DMixingSourceMode = .bypass
var pointSourceInHeadMode: AVAudio3DMixingPointSourceInHeadMode = .bypass
var renderingAlgorithm = AVAudio3DMixingRenderingAlgorithm.sphericalHead
var rate: Float = 1.2
var reverbBlend: Float = 40.0
var obstruction: Float = -100.0
var occlusion: Float = -100.0
var position = AVAudio3DPoint(x: 0, y: 0, z: 10)
let audioNode = SCNNode()
override func viewDidLoad() {
super.viewDidLoad()
let myScene = SCNScene()
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
cameraNode.position = SCNVector3(0, 0, 0)
myScene.rootNode.addChildNode(cameraNode)
// let sceneView = view as! SCNView
sceneView.scene = myScene
sceneView.backgroundColor = UIColor.orange
let myPath = Bundle.main.path(forResource: "Mono_Audio", ofType: "mp3")
let myURL = URL(fileURLWithPath: myPath!)
let mySource = SCNAudioSource(url: myURL)!
mySource.loops = true
mySource.isPositional = true // Positional Audio
mySource.shouldStream = false // FALSE for Positional Audio
mySource.volume = volume
mySource.reverbBlend = reverbBlend
mySource.rate = rate
mySource.load()
let player = SCNAudioPlayer(source: mySource)
let sphere: SCNGeometry = SCNSphere(radius: 0.1)
let sphereNode = SCNNode(geometry: sphere)
sphereNode.addChildNode(audioNode)
myScene.rootNode.addChildNode(sphereNode)
audioNode.addAudioPlayer(player)
sceneView.audioEnvironmentNode.distanceAttenuationParameters.maximumDistance = 2
sceneView.audioEnvironmentNode.distanceAttenuationParameters.referenceDistance = 0.1
sceneView.audioEnvironmentNode.renderingAlgorithm = .auto
// sceneView.audioEnvironmentNode.reverbParameters.enable = true
// sceneView.audioEnvironmentNode.reverbParameters.loadFactoryReverbPreset(.plate)
let hither = SCNAction.moveBy(x: 0, y: 0, z: 1, duration: 2)
let thither = SCNAction.moveBy(x: 0, y: 0, z: -1, duration: 2)
let sequence = SCNAction.sequence([hither, thither])
let loop = SCNAction.repeatForever(sequence)
sphereNode.runAction(loop)
}
}
And, yes, you're absolutely right – there are some obligatory settings.
But there are 7 of them:
use AVAudioMixing protocol with its stubs (properties and methods).
use MONO audio file.
use source.isPositional = true.
use source.shouldStream = false.
assign maximumDistance value to distanceAttenuationParameters property.
assign referenceDistance value to distanceAttenuationParameters property.
and location of mySource.load() is very important in your code.
P.S. If the aforementioned tips didn't help you, then use additional instance properties to make your sound even quieter using a graph, obstacles and orientation of implicit listener:
var rolloffFactor: Float { get set } // attenuation's graph, default = 1
var obstruction: Float { get set } // default = 0.0
var occlusion: Float { get set } // default = 0.0
var listenerAngularOrientation: AVAudio3DAngularOrientation { get set } //(0,0,0)
It definitely works if you'll write it in Objective-C.
In this example the distance of audioNode is 1 meter away from a listener.
If none of the above answers seem to work, try the following code:
sceneView.audioEnvironmentNode.reverbParameters.enable = true
And if even these seem to barely work, or if you wanna optimal performance, there is a property called level where you can set the level of how spatial the code can be.
sceneView.audioEnvironmentNode.reverbParameters.level = 40
(the level of the reverbParameters ranges between -40 to 40 parameters)

SceneKit avoid lighting on specific node

In SceneKit I'm building a node made of lines to draw the XYZ axes at the center of the scene, like in Cinema4D.
I would like these 3 nodes not to participate to the global lighting and be viewable even if the light is dark / inexistent / too strong. In the picture below you can see that the Z axis appears too heavily lighten and can't be seen.
Is there a way to stop a node participating to the scene's lighting, like with category masks for physics?
In this case, how would the node be lighten in order for it to appear anyway?
SCNLight has a categoryBitMask property. This lets you choose which nodes are affected by the light (Although this is ignored for ambient lights). You could have 2 light source categories, one for your main scene, and another that only affects your lines.
Here is a simple example with 2 nodes, each lit with a different colour light:
struct LightType {
static let light1:Int = 0x1 << 1
static let light2:Int = 0x1 << 2
}
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let scene = SCNScene(named: "art.scnassets/scene.scn")!
let lightNode1 = SCNNode()
lightNode1.light = SCNLight()
lightNode1.light!.type = .omni
lightNode1.light!.color = UIColor.yellow
lightNode1.position = SCNVector3(x: 0, y: 10, z: 10)
lightNode1.light!.categoryBitMask = LightType.light1
scene.rootNode.addChildNode(lightNode1)
let lightNode2 = SCNNode()
lightNode2.light = SCNLight()
lightNode2.light!.type = .omni
lightNode2.light!.color = UIColor.red
lightNode2.position = SCNVector3(x: 0, y: 10, z: 10)
lightNode2.light!.categoryBitMask = LightType.light2
scene.rootNode.addChildNode(lightNode2)
let sphere1 = scene.rootNode.childNode(withName: "sphere1", recursively: true)!
sphere1.categoryBitMask = LightType.light1
let sphere2 = scene.rootNode.childNode(withName: "sphere2", recursively: true)!
sphere2.categoryBitMask = LightType.light2
let scnView = self.view as! SCNView
scnView.scene = scene
}
}
I think it would be much easier to set the material's lightning model to constant.
yourNode.geometry?.firstMaterial?.lightingModel = SCNMaterial.LightingModel.constant