When I scour SO, I saw that it's a bit complex to port scan a UDP port than a TCP port, why?
Actually, you cannot really do a UDP port scan. While an open TCP port generally replies to a simple SYN probe, UDP has no concept for a socket connection. Simply put, there's no single probe message to see if a UDP port is listening.
Accordingly, you might not get any reply from an open UDP port unless you guess the right application protocol behind it and it chooses to reply (a DNS server replies to a DNS request, an SNTP server to an SNTP request, etc). Without a reply, you won't know whether a certain port is closed, whether the firewall has filtered the packet, or whether the application just chose to ignore your request.
Basically, you can only probe UDP ports that you know or guess the application-layer protocol of, and you can talk it into replying. That is a lot more complicated than sending a generic TCP SYN.
Of course, you could try to simply check for ICMP destination port unreachable messages for closed ports, but these are usually filtered (or not sent at all) on the open Internet and in many other scenarios.
With TCP there is a standardized connection setup process that is implemented by the operating system and applies regardless of what application protocol is being used. So you can send a "syn" packet as a probe and based on the response you can determine if the port is "open" (the server proceeds with the next step in the connection setup process, sending the "syn-ack"), "closed" (the connection is rejected with an ICMP error) or "filtered" (there is no response at all, which likely indicates the traffic is blocked by a firewall).
With UDP on the other hand "closed" ports will trigger a response from the operating system, but for open ports the operating system will simply pass the packet to the server application without generating any response of it's own. UDP server applications will normally not send a response to packets they do not understand.
So when you send a UDP probe packet and get no response you have no way of knowing whether your packet was filtered by a firewall or whether it was delivered successfully to an application that did not respond (either because it could not interpret the packet or because of it's own internal policies).
To further illustrate the challenge of scanning for UDP here are some details about how the functionality is implemented in nmap which is still probably the most popular port scanner nowadays:
UDP scan works by sending a UDP packet to every targeted port. For some common ports such as 53 and 161, a protocol-specific payload is sent to increase response rate, but for most ports the packet is empty unless the --data, --data-string, or --data-length options are specified. If an ICMP port unreachable error (type 3, code 3) is returned, the port is closed. Other ICMP unreachable errors (type 3, codes 0, 1, 2, 9, 10, or 13) mark the port as filtered. Occasionally, a service will respond with a UDP packet, proving that it is open. If no response is received after retransmissions, the port is classified as open|filtered. This means that the port could be open, or perhaps packet filters are blocking the communication. Version detection (-sV) can be used to help differentiate the truly open ports from the filtered ones.
A big challenge with UDP scanning is doing it quickly. Open and filtered ports rarely send any response, leaving Nmap to time out and then conduct retransmissions just in case the probe or response were lost. Closed ports are often an even bigger problem. They usually send back an ICMP port unreachable error. But unlike the RST packets sent by closed TCP ports in response to a SYN or connect scan, many hosts rate limit ICMP port unreachable messages by default. Linux and Solaris are particularly strict about this. For example, the Linux 2.4.20 kernel limits destination unreachable messages to one per second (in net/ipv4/icmp.c).
The last paragraph must be outdated, not sure about current implementations.
Nmap detects rate limiting and slows down accordingly to avoid flooding the network with useless packets that the target machine will drop. Unfortunately, a Linux-style limit of one packet per second makes a 65,536-port scan take more than 18 hours. Ideas for speeding your UDP scans up include scanning more hosts in parallel, doing a quick scan of just the popular ports first, scanning from behind the firewall, and using --host-timeout to skip slow hosts.
Source: nmap - Port Scanning Techniques
I seem to remember from a long time ago that the Unicorn scanner has its own way of scanning UDP but can't find the details right now. Since each port scanner has its own way of telling an open port from a closed port it can guess wrong, and results may vary. The best way would be to use a tool like Scapy to craft your own packets and interprets the responses for yourself.