The blockchain is synchronous by design and doesn't allow you to perform actions between blocks in a single transaction. This means, that if you want to "wait X seconds and then do something else" you'd need to do it in 2 transactions.
Some actor will always have to spend the gas to make these transactions. If you're looking for something like a cron scheduler, trigger-based mechanism, or an if-this-do-that type deal, there are two ways you can do this, with either decentralized or centralized automation.
You can use a decentralized network of oracles to call smart contracts. Using Chainlink Keepers can call the function you specified at any time or event trigger focused. The oracles pay the gas associated with the call, and you pay for a subscription model to the Chainlink nodes.
The way, you're contract stays decentralized all the way down to the automation level, and you never have to worry about a centralized actor intentionally not sending a transaction. Another option to do this would be Gelato.
You can also have "traditional" infrastructure call your functions on a schedule, just keep in mind this means that you are relying on a centralized actor in your contracts.
There are forms of centralized automation that you can take such as:
- Your own server/set of scripts
- Openzeppelin Defender
- Incentive Mechanisms for people to call your functions
Disclaimer: I work on the Chainlink Project
This is similar to this StackOverflow question.